【问题标题】:Batch script fails on filenames with parenthesis批处理脚本在带括号的文件名上失败
【发布时间】:2016-05-06 00:57:59
【问题描述】:

我写了一个批处理脚本:

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

谁能告诉这个问题的原因以及如何解决它?

【问题讨论】:

  • 它很可能会失败,因为括号是批处理文件中的运算符。正如您在do 声明中看到的那样?当您使用带括号的文件时,它可能会尝试找到另一个操作。是否绝对有必要使用括号?如果是这样,那么您需要研究一种使用textA = "text(name)" 等(或类似代码)设置值的方法,以确保括号被读取为变量,而不是另一个函数。这可能不是正在发生的问题,但这是我的最佳猜测。
  • 尝试将dir /a %%f 替换为dir /a "%%~f",并在最后一行中将%%f -mx0 替换为"%%~f" -mx0
  • @rojo 试过了,不行。
  • edit您的问题并显示呼叫线路以查看%*解决的问题。

标签: windows batch-file


【解决方案1】:

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

  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
        )
    )
    

    此方法解决了括号 () 以及 &^ 的问题,但它对批处理脚本具有特殊含义的所有字符(如 <、@ 987654331@和|

  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
    

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

【讨论】:

  • 谢谢你,它似乎工作。你能解释一下为什么在 for 循环中添加 endlocalsetlocal 吗?
  • 这是为了避免在启用延迟扩展期间发生%%F 实例扩展时丢失感叹号;同时我在answer...中扩展了解释...
  • 感谢您的详细解释。顺便说一句,dir /A "%%~fF" | > nul 2>&1 findstr "DIR" && (...) || (...) 如果用于检测%%F 是否是一个文件夹,我找到了一种更简单的方法:if exist "%%~F\" (...) else (...) (ref)。
  • 不幸的是,如果文件是something^with caret and space.txt,这似乎被破坏了。将set "ARGS=%*" 替换为set ARGS=%* 将使其正常工作。但是对于something^with^caret.txt(完整路径中不包含空格),两种方式都失败了。
  • 如何将这些参数传递给批处理脚本?必须引用此类参数(""),否则命令行解析器会混淆...
猜你喜欢
  • 2012-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-16
  • 2023-02-14
  • 2020-03-22
  • 1970-01-01
相关资源
最近更新 更多