批处理脚本在带括号的文件名上失败

时间:2016-05-02 17:49:18

标签: windows batch-file

我写了一个批处理脚本:

@echo off
set "zip=C:\Program Files\7-Zip\7z.exe"
for %%f in (%*) do (
    if exist "%%~f\" (
        "%zip%" a -tzip "%%~f.zip" "%%~f\*" -mx0
    ) else (
        "%zip%" a -tzip "%%~f.zip" %%f -mx0
    )
)

当用户选择多个文件/文件夹并将其拖到脚本文件中时,拖动的每个文件/文件夹都会打包成一个zip文件。

在大多数情况下都可以正常工作。但是,如果被拖动的文件位于其文件名包含括号的目录中,例如" myfolder(large)",则脚本将失败。

任何人都能说出导致这个问题的原因以及解决方法吗?

1 个答案:

答案 0 :(得分:2)

对于这个问题,我看到以下选项:

  1. 使用临时变量^转义括号:

    @echo off
    set "ZIP=C:\Program Files\7-Zip\7z.exe"
    set "ARGS=%*"
    set "ARGS=%ARGS:^=^^%"
    set "ARGS=%ARGS:&=^&%"
    set "ARGS=%ARGS:(=^(%"
    set "ARGS=%ARGS:)=^)%"
    for %%F in (%ARGS%) do (
        dir /A "%%~fF" | > nul 2>&1 findstr "DIR" && (
            "%ZIP%" a -tzip "%%~F.zip" "%%~F\*" -mx0
        ) || (
            "%ZIP%" a -tzip "%%~F.zip" "%%~fF" -mx0
        )
    )
    

    此方法解决了括号()以及&^的问题,但它对所有对批处理具有特殊含义的字符都不具有强大的作用脚本,例如<>|

  2. 为有问题的字符串启用和应用delayed expansion

    @echo off
    set "ZIP=C:\Program Files\7-Zip\7z.exe"
    set "ARGS=%*"
    setlocal EnableDelayedExpansion
    for %%F in (!ARGS!) do (
        endlocal
        dir /A "%%~fF" | > nul 2>&1 findstr "DIR" && (
            "%ZIP%" a -tzip "%%~F.zip" "%%~F\*" -mx0
        ) || (
            "%ZIP%" a -tzip "%%~F.zip" "%%~fF" -mx0
        )
        setlocal
    )
    endlocal
    

    我更喜欢这种方法,因为它解决了所有特殊字符的问题。在扩展%%F变量实例期间,将循环内部的延迟扩展切换(依赖于禁用的Windows默认设置),以便在字符串包含感叹号时出现问题{{} 1}}。这里的问题是延迟扩展会消耗命令行遇到的!。在执行延迟扩展之前,!变量for会扩展为其值;因此,如果%%F值包含%%F,则它会消失 - 除非禁用延迟展开,!没有特别含义。