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

Windows 批处理脚本在带括号的文件名上失败,windows,batch-file,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 ) ) 当用户选择多个文件/文件夹并将其拖动到脚本文件时,拖动的

我编写了一个批处理脚本:

@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)”,则脚本将失败


有人能告诉我是什么导致了这个问题以及如何解决它吗?

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

  • 通过使用中间变量对括号进行转义^:

    @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
        )
    )
    
    此方法解决了括号
    以及
    &
    ^
    的问题,但它对批处理脚本中具有特殊含义的所有字符(如
    |
    )都不可靠

  • 启用和应用有问题的字符串:

    @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
    
    我更喜欢这种方法,因为它解决了所有特殊字符的问题。循环内部延迟扩展的切换(取决于禁用的Windows默认设置)是为了在扩展
    %%F
    变量实例期间禁用它,否则在字符串包含感叹号
    的情况下会出现问题。这里的问题是延迟扩展会消耗
    在命令行上遇到。在执行延迟扩展之前,将
    %%F
    等变量的
    扩展到其值;因此,如果
    %%F
    值包含
    它将消失-除非禁用延迟扩展,其中
    没有特别的含义


  • 它很可能失败,因为括号是批处理文件中的运算符。正如您在
    do
    语句中看到的那样?当您使用括号中的文件时,它可能会试图找到另一个要执行的操作。是否绝对有必要使用括号?如果是这样,那么您需要研究一种方法,使用
    textA=“text(name)”
    等(或类似代码)设置值,以确保括号作为变量而不是另一个函数读取。这可能不是正在发生的问题,但这是我最好的猜测。请尝试将
    dir/a%%f
    替换为
    dir/a“%%f”
    ,并在最后一个邮政编码行中,将
    %%f-mx0
    替换为
    “%%f”-mx0
    @rojo它已尝试过,但不起作用。请提出您的问题并显示呼叫线路,以查看
    %*
    解决方案。谢谢,它似乎起作用了。您能解释一下为什么在for循环中添加
    endlocal
    setlocal
    吗?这是为了避免感叹号丢失,在启用延迟扩展期间扩展
    %%F
    实例时会出现这种情况;同时,我扩展了…中的解释,感谢您的详细解释。顺便说一句,
    dir/A“%%~fF”|>nul2>&1 findstr“dir”&(…)|(…)
    如果要检测
    %%F
    是否是一个文件夹,我找到了一种更简单的方法:
    如果存在“%%~F\”(…)else(…)
    ()。不幸的是,如果一个文件是
    带有插入符号和空格的文件,这似乎会被破坏。将
    set“ARGS=%*”
    替换为
    set ARGS=%*
    将使其正常工作。但是对于带有^caret.txt的
    something^(完整路径中不包含空格),两种方法都会失败。如何将这些参数传递给批处理脚本?这些参数必须被引用(
    “”
    ),否则命令行解析器会混淆。。。