【问题标题】:Ignore percent sign in batch file忽略批处理文件中的百分号
【发布时间】:2021-11-28 10:31:37
【问题描述】:

我有一个批处理文件,可以将文件从一个文件夹移动到另一个文件夹。批处理文件是由另一个进程生成的。

我需要移动的一些文件中包含字符串“%20”:

move /y "\\myserver\myfolder\file%20name.txt" "\\myserver\otherfolder"

这失败了,因为它试图找到一个文件名:

\\myserver\myfolder\file0name.txt

有什么方法可以忽略%?我无法更改生成的文件以逃避这种情况,例如通过加倍百分号 (%%)、转义 /^(插入符号)等。

【问题讨论】:

  • 你应该接受 rud3y 的回答
  • 正如我所说,我无法更改生成的文件。我得到带有 % 符号的文件为:file%20name.txt。我无法在其中添加额外的 %。

标签: batch-file escaping


【解决方案1】:

您应该可以使用插入符号 (^) to escape a percent sign

编者注:链接已失效;无论哪种方式:这是% 本身转义%,但仅在批处理文件中,而不是在命令提示符下; ^ 从不转义%,但在命令提示符可以间接使用它来防止变量扩展,在未加引号 仅限字符串。

%2 消失的原因是批处理文件替换了传入的第二个参数,而您似乎没有第二个参数。解决这个问题的一种方法是实际尝试foo.bat ^%1 ^%2...,这样当在命令中遇到%2 时,它实际上会被替换为文字%2

【讨论】:

  • 不能用插入符号转义百分号,只能用百分号
  • @mklement0 从技术上讲,您无法在命令行上转义百分号。它似乎起作用的唯一原因是 cmd.exe 在%username^% 中搜索变量username^,因此您也可以使用%user^name% 它与转义百分比无关。顺便说一句,foo.bat ^%1 ^%2 根本没用,因为在扩展 %1%2 之后,插入符号就被删除了。另见How variables are expanded
  • 正如@jeb 指出的那样,^ 实际上无法转义%,尽管通常 在不带引号的字符串中充当转义字符。但是,您可以使用^,通过将其放置在变量名之前、之后或内部来有效地抑制变量扩展,但仅适用于命令行,而不是在批处理文件中。答案的其余部分为 OP 的非常具体的问题提供了一个巧妙的解决方案:需要处理格式错误的自动生成的批处理文件; OP 问题的这种特殊性与问题标题的通用性不一致,这会引起混淆。
  • @jeb:再次感谢您对% 的澄清。 ^%2 中的 ^ 在这里没用,但没有害处:建议的解决方案适用于 ^%2%2,因为据我所知,交互式 cmd.exe shell 永远不会有参数,并且所以像%2 这样的引用会按原样保留(被视为文字;相比之下,当从另一个批处理文件 调用时,您必须使用%%2)。使用%^2 来保证安全和明确也是一种选择。
【解决方案2】:

在批处理文件中,百分号可以通过使用双百分号 (%%) 来“转义”。 这样,将在命令行中使用单个百分号。来自http://www.robvanderwoude.com/escapechars.php

【讨论】:

  • 要理解为什么百分号只能用百分号转义而不用插入符号,您可以阅读how cmd.exe parse scripts
  • 如果您仍然需要^ 来转义变量,但如果您是命令行的一部分,则将^ 放在变量名中将阻止它扩展。像%Variable^Name% 这样的东西会转义为%VariableName% 而不会被扩展。
【解决方案3】:

在这种情况下,您需要使用%%。通常使用 ^(插入符号)会起作用,但对于 % 符号,您需要加倍。

%%1%%iecho.%%~dp1的情况下,因为%表示来自命令或来自变量的输入(当被%包围时;%variable%

实现您的需要:

move /y "\\myserver\myfolder\file%%20name.txt" "\\myserver\otherfolder"

我希望这会有所帮助!

【讨论】:

  • 请注意,%% 仅适用于批处理文件,而不适用于命令提示符本身。在命令提示符本身上,插入符号将转义百分号^% 显示%
  • @MichaelPlautz:关于%% 不能在命令提示符下工作的好点。然而,^ 确实 not 逃脱 % 那里 - 一个微妙的区别,但重要的是:^% 只打印 %,因为 ^ 放在 any 之前i> 不带引号的字符串中的 char 在输出中被丢弃 - 无论该 char 是否需要转义。但是,由于^ 无法逃脱%% 的“特殊性”not^ 停用 - 尝试echo ^%CD% - 它与echo %CD% 相同。 echo ^%CD^% 有效,但只是因为 cmd.exe 现在认为 变量名CD^ 和一个 undefined 变量。参考按原样保留。
【解决方案4】:

我想我有一个部分解决方案正在工作。如果您只想传输名称中包含“%20”字符串的文件而不是寻找更广泛的解决方案,您可以使用 %%2 作为第二个参数来调用第一个批处理文件。这样,当您的程序在遇到文本名称中的 %2 时尝试获取第二个参数时,它会将 %2 替换为转义的 %2,而文件名保持不变。

希望这行得通!

【讨论】:

  • 这与接受的答案基本相同,其中建议使用^%2 作为第二个参数;唯一的区别是语法 - ^%2%%2,这可以通过在命令行上生成文字 %^ 实际上在这里没有效果)与在批处理文件中的区别来解释.
【解决方案5】:

问题的标题非常通用,难免会吸引很多寻求通用解决方案的读者。
相比之下,OP 的问题是奇异:需要处理格式错误且无法修改的自动生成的批处理文件% 符号未在其中正确转义。
accepted answer特定和奇异的问题提供了一个巧妙的解决方案,但必然会在通用问题方面造成混乱。

如果我们专注于通用问题

如何在批处理文件/命令行中使用%作为文字字符?

  • 批处理文件中,始终将%转义为%%,无论是否在未加引号的字符串中;例如,以下产生My %USERNAME% is jdoe

      echo My %%USERNAME%% is %USERNAME%
      echo "My %%USERNAME%% is %USERNAME%"
    
  • 命令行(以交互方式) - 以及在使用脚本的shell调用函数时语言 - 行为从根本上不同于批处理文件中的行为:从技术上讲,% 不能在那里转义 并且没有单一解决方法适用于所有情况

    • 未引用字符串中,您可以使用 "^ name-disrupter" 技巧:为简单起见,放置一个^ 在每个 % char 之前,但请注意,从技术上讲,您不是 转义 % 那样(更多信息见下文);例如,以下再次产生类似My %USERNAME% is jdoe:

       echo My ^%USERNAME^% is %USERNAME%
      
    • 双引号字符串中,您无法转义%,但有解决方法

      • 你可以像上面那样使用unquoted字符串,这需要你另外 ^-转义所有其他shell元字符,这很麻烦;这些元字符是:<space> & | < > "

      • 或者,除非您正在调用 批处理文件,您可以单独双引号 % chars 作为复合参数的一部分(大多数外部程序和脚本引擎将复合参数如 "%"USERNAME"%" 解析为逐字字符串 %USERNAME%):

         some_exe My "%"USERNAME"%" is %USERNAME%
        
    • 通过脚本语言,如果您知道自己正在调用二进制可执行文件,您或许可以通过放弃 shell 调用函数来支持“无壳”变体来避免整个问题,例如using execFileSync instead of execSync in Node.js.


可选的背景信息re 命令行(交互式)使用:

感谢 jeb 对本节的帮助。

命令行(以交互方式)上,% 在技术上根本无法转义;虽然^通常cmd.exe的转义字符,但它确实适用于%

如前所述,双引号字符串没有解决方案,但未加引号解决方法 /em> 字符串:

^name-disrupter”技巧(类似于^%USERNAME^%)起作用的原因是:

  • 它“破坏”了变量名;也就是说,在上面的示例中,cmd.exe 会查找名为 USERNAME^ 的变量,但该变量(希望)不存在。

  • 在命令行 - 与批处理文件不同 - 对 undefined 变量的引用按原样保留

从技术上讲,变量名中的单个 ^ - 在其中的任何位置,只要它不与另一个 ^ 相邻 - 就足够了,例如,%USERNAME^%,就足够了,但是我建议采用有条不紊地将^ 放在每个 % 为简单起见的惯例,因为它也适用于 up 20^% 等情况,中断甚至不是必要的,而是良性的,因此您可以有条不紊地应用它,而无需考虑输入字符串的细节。 p>

^打开 % 之前是良性的,因为^ 转义了下一个字符,无论该字符是否需要转义 - 或者,在这种情况下, 可以被转义 - 或不能。最终效果是,此类^ 实例最终会从未引用字符串中删除

很大程度上假设的警告^ 实际上是变量名中的合法字符(参见 cmets 中 jeb 的示例);如果您的变量名 ^ 结尾,只需将“破坏性”^ 放在变量名中的某处else,只要它不直接与另一个 @ 相邻即可987654368@(因为这会导致 ^ 出现在结果字符串中)。
也就是说,如果您的变量具有诸如 ^b^ 之类的名称(非常不可能),那么您就不走运了。

【讨论】:

  • 对我来说 "%%" 在 Windows 7 中为批处理文件工作 sendto: command ffmpeg -i %1 ./image"%%"05d.png 在 cmd 中的命令是 ...image%05d.png
  • @Phann:重新批处理文件:您不需要 "..." 周围的 %%,我建议一般不要使用它,因为并非所有目标程序都可能剥离令牌内部 @ 987654376@ 字符。为你。如果一个标记需要对其中包含的 其他 个字符进行双引号,则将其作为一个整体双引号。
  • 查看我的answer 如何在命令行上使用文字百分号,甚至在引号内
【解决方案6】:

如何在不修改文件的情况下在批处理文件中“转义”** 最初的问题是关于生成的文件,该文件无法修改,但包含以下行:

move /y "\\myserver\myfolder\file%20name.txt" "\\myserver\otherfolder"

这可以通过使用适当的参数调用脚本来部分解决(%1%2、...)

@echo off

set "per=%%"
call generated_file.bat %%per%%1 %%per%%2 %%per%%3 %%per%%4

这只是将参数设置为:

arg1="%1"
arg2="%2"
...

如何在命令行中添加文字百分号

mklement0 describes the problem,在命令行上转义百分号很棘手,而且在引号内似乎是不可能的。

不过还是可以用一点小技巧来解决的。

for %Q in ("%") do echo "file%~Q20name.txt"

%Q 包含 "%"%~Q 仅扩展为 %,与引号无关。

或者避免%~使用

for /F %Q in ("%") do echo "file%Q20name.txt"

【讨论】:

    猜你喜欢
    • 2022-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多