我试图创build一个batch file,可以有其他文件放在它上面。 具体来说,我使用ffmpeg来编辑手持式录音机产生的audio文件。 问题是使用与&符号的文件名。 即使在引用input时,也只有当文件被放到它上面时,才会将&放下。 如果文件名input是在命令行input的,脚本工作正常。 在cmd
窗口closures之前,我暂时看到文件名的其余部分,并显示错误,说明它不被识别为有效的命令。
这是我的脚本:
rem更改为驱动器和input文件的目录 %〜D1 cd%〜p1 rem ffmpeg:混合到一个通道,加倍音量 %HOMEDRIVE %% HOMEPATH%\ ffmpeg.exe -i“%〜nx1”-ac 1 -vol 1024“%〜n1 fixed%〜x1” 暂停
下面是删除"ch17&18.mp3"
后在命令行上出现的内容:
C:\ Users \ computergeeksjw \ Desktop> C:\ Users \ computergeeksjw \ ffmpeg.exe -i“ch17”-ac 1 -vol 1024“ch17 fixed” [...] ch17:没有这样的文件或目录
万一它很重要:我正在使用Windows 8开发人员预览。 这是否导致我的问题? 在Windows 7或更早版本上是否出现相同的错误?
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 . . .
如果忽略整个命令周围的引号,则会看到文件参数周围没有引号。 没有特殊的字符,所以没有问题。
现在拖放“a 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如何检测名称中的空间并将文件用引号引起来。 再次没有问题。
现在拖放“a&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 )
我沉默敬畏地欣赏dbenham的批处理编程技巧。 我尝试了他的解决办法,偶然发现了我在这里提出的两个问题,因为我没有足够的声望评论:
他的批处理模板的第15行的最后一个引号前面似乎有一个额外的空格。 我想这应该是:
set "args=!cmd2:~0,-1!"
没有那么好的批量编程知识的人可能会遇到严重的问题,就像我一样。 我试过,但无法编辑dbenham的帖子,因为愚蠢的“编辑必须至少有6个字符”的限制。
该解决方案通常不适用于包含,
(逗号)或文件夹的文件/文件夹;
(分号)完整路径。 它可以被修改以便在通过将第20行中的引号括起来的情况下只有一个文件/文件夹被丢弃到批处理文件中的情况下工作:
for %%F in ("!args!") do (
当多个文件/文件夹被拖放到一个批处理文件中时,恐怕没有一个可以应对文件路径中的逗号/分号的Windows错误的通用解决方法。 Windows的SendTo机制显然有相同的缺陷(bug),所以不能用来解决拖放的问题。 这是由微软最终解决这个错误。