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