Windows拖放功能中存在一個長期存在的錯誤,該功能與文件路徑有關,其中包含&
或^
但不包含<space>
。
如果文件路徑至少包含一個<space>
,則Windows會自動將引號括起來,以便正確解析該路徑。如果文件路徑包含&
或^
,Windows應該做同樣的事情,但它不會。
如果您創建以下簡單批處理文件並將文件拖到其上,您可以看到問題。
@echo off
setlocal enableDelayedExpansion
echo cmd=!cmdcmdline!
echo %%1="%~1"
pause
exit
!cmdcmdline!變量包含啓動批處理文件的實際命令。 批處理文件輸出命令行和第一個參數。
如果你拖放一個文件名爲「a.txt中」你如果不顧周圍的整個命令你看到身邊有該文件的說法沒有引號引號得到
cmd=cmd /c ""C:\test\drag.bat" C:\test\a.txt"
%1=C:\test\a.txt
Press any key to continue . . .
。沒有特殊字符,所以沒有問題。
現在拖放「一個b.txt」,你會得到
cmd=cmd /c ""C:\test\drag.bat" "C:\test\a b.txt""
%1="C:\test\a b.txt"
Press any key to continue . . .
你可以看到Windows如何檢測的空間的名稱和封閉在報價文件。再次沒有問題。
現在拖放「一個& b.txt」,你會得到
cmd=cmd /c ""C:\test\drag.bat" C:\test\a&b.txt"
%1=C:\test\a
Press any key to continue . . .
Windows沒有找到名字空間,所以它不會在引號括起來。大問題! Windows將「C:\ test \ a」傳遞給批處理文件,並在批處理文件完成後將「b.txt」作爲第二個文件執行。批處理文件中的硬EXIT命令可防止批處理後執行任何分割文件名。當然b.txt永遠不會執行。但如果該文件被命名爲「a & b.bat」和「b.bat」,那麼如果硬EXIT不在批處理文件中,則可能會出現問題。
是可能的拖動多個文件到一個批處理文件,而且每一個應作爲一個參數傳遞。
的!CMDCMDLINE!是可靠訪問拖放參數的唯一方法。但是,如果文件在正常調用批處理文件時作爲普通參數傳遞,那將無法工作。
下面是一個批處理文件,可以使用拖放檢測,如果它被稱爲和降對一個正常通話。 (這不是防彈的,但我認爲它應該可以在大多數情況下工作)它將一次一個地處理每個文件參數,而不管呼叫類型如何。 (該過程簡單回顯文件名,但可以替換所需的任何處理。)如果使用拖放方式調用批處理,則會執行硬性退出以防止分割文件名。
@echo off
setlocal disableDelayedExpansion
::
:: first assume normal call, get args from %*
set args=%*
set "dragDrop="
::
:: Now check if drag&drop situation by looking for %0 in !cmdcmdline!
:: if found then set drag&drop flag and get args from !cmdcmdline!
setlocal enableDelayedExpansion
set "cmd=!cmdcmdline!"
set "cmd2=!cmd:*%~f0=!"
if "!cmd2!" neq "!cmd!" (
set dragDrop=1
set "args=!cmd2:~0,-1! "
set "args=!args:* =!"
)
::
:: Process the args
for %%F in (!args!) do (
if "!!"=="" endlocal & set "dragDrop=%dragDrop%"
rem ------------------------------------------------
rem - Your file processing starts here.
rem - Each file will be processed one at a time
rem - The file path will be in %%F
rem -
echo Process file "%%~F"
rem -
rem - Your file processing ends here
rem -------------------------------------------------
)
::
:: If drag&drop then must do a hard exit to prevent unwanted execution
:: of any split drag&drop filename argument
if defined dragDrop (
pause
exit
)
它看起來像你現有的批處理僅用於處理一個文件。我無法確定是否需要修改調用以支持多個文件。我修改了上述批處理以僅處理第一個參數,並將您的進程替換爲參數處理循環。這是未經測試的,但我認爲它應該適合你。
@echo off
setlocal disableDelayedExpansion
::
:: first assume normal call, get args from %*
set args=%*
set "dragDrop="
::
:: Now check if drag&drop situation by looking for %0 in !cmdcmdline!
:: if found then set drag&drop flag and get args from !cmdcmdline!
setlocal enableDelayedExpansion
set "cmd=!cmdcmdline!"
set "cmd2=!cmd:*%~f0=!"
if "!cmd2!" neq "!cmd!" (
set dragDrop=1
set "args=!cmd2:~0,-1! "
set "args=!args:* =!"
)
::
:: Process the first argument only
for %%F in (!args!) do (
if "!!"=="" endlocal & set "dragDrop=%dragDrop%"
rem ------------------------------------------------
rem - Your file processing starts here.
rem - Use %%F wherever you would normally use %1
rem
rem Change to drive and directory of input file
%%~dF
cd %%~pF
rem ffmpeg: mix to one channel, double the volume
%HOMEDRIVE%%HOMEPATH%\ffmpeg.exe -i "%%~nxF" -ac 1 -vol 1024 "%%~nF fixed%%~xF"
rem
rem - Your file processing ends here
rem -------------------------------------------------
goto :continue
)
:continue
if defined dragDrop (
pause
exit
)
精彩!很棒。如果不是麻煩的話,我會喜歡逐行解釋腳本的工作原理,因爲這是我的第一批腳本(儘管不是我的第一次編程經驗)。謝謝! – stephenwade 2011-12-26 01:41:03