Windows
bat
dos

バッチの引数にファイルパスを渡すと壊れるのな


ファイル名破壊を回避するサブルーチン

以下の バッチサブルーチンは、引数を全てダブルクオーテーションで囲み直し、ファイル名の破壊を防ぐ。

:quote_args

set __QUOTE_ARGS__=
setlocal enabledelayedexpansion
set "ARGS=%* "
:next
for %%a in (!ARGS!) do (
if '%%a' == '"%%~a"' (
set "BUFF=!BUFF! %%a"
set "ARGS=!ARGS:*" =!"
goto next
)
for %%b in ("!ARGS: =" "!") do (
set "BUFF=!BUFF! %%b"
set "ARGS=!ARGS:* =!"
goto next
)
)
endlocal & call set "__QUOTE_ARGS__=%BUFF:~1%"
exit /b

使い方はそのまま既存のバッチに埋め込んで簡単に使用できる。

@echo off

rem 既存バッチ全体をサブルーチン化(main)して呼び直す
call :quote_args %*
call :main %__QUOTE_ARGS__%
:main

rem 既存バッチスクリプト本体


for %%a in (%*) do (
echo %%a
)


exit /b

rem 引数処理サブルーチン埋め込み
:quote_args
set __QUOTE_ARGS__=

こんな意味不明のコードを埋め込みたくなければ、そのまま外出しの BAT ファイルにして外部ライブラリとして呼び出してもよい。

@echo off

rem 外部ファイルのライブラリとして呼び出す
call .\quote_args.bat %*
call :main %__QUOTE_ARGS__%
:main

rem 既存バッチスクリプト本体


for %%a in (%*) do (
echo %%a
)


既存バッチを編集することさえ避けたいのなら、逆に、ラッパーにして既存バッチを呼び出すことも可能だ。

@echo off

rem 既存 BAT に引数を渡しなおす
call :quote_args %*
call .\legacy.bat %__QUOTE_ARGS__%
exit /b

:quote_args
set __QUOTE_ARGS__=


これで、バッチにファイルをDrag & Dropしても常に有効なフルパス名が引き渡せるようになる。

ただし一部使用できない記号(%,!,&,^)がある。


解説

解説はしない、腹が立つので。

Qiitaの皆さんはこういうくだらない事にかかずらってはならない。