这是因为? 将扩展为一个长度为一个字符的文件名列表。 “裸”for 将该列表用作文件名列表。
如果您运行以下命令,您将看到它的实际效果:
c:\> echo xx >a
c:\> echo xx >b
c:\> for %i in (1, ?) do echo %x
1
a
b
如果您查看Rob van der Woude's excellent scripting pages,您会发现for page 具有处理命令输出、数字和文件的选项——它并不真正适合任意字符串。
解决此问题的一种方法是提供您自己的for-like 命令,如下例所示:
@echo off
setlocal enableextensions enabledelayedexpansion
rem Call the callback function for each argument.
set escapee=/
call :doFor :processEach 1 2 ? 4 5
echo.Escapee was %escapee%
rem Execute simple command for each argument.
call :doFor echo 6 7 ? 9 10
endlocal
goto :eof
:processEach
set escapee=%escapee%%1/
goto :eof
:doFor
setlocal
rem Get action.
set cbAction=%1
shift
:dfloop
rem Process each argument with callback or command.
if not "%1" == "" (
call %cbAction% %1
shift
goto :dfloop
)
endlocal&&set escapee=%escapee%
goto :eof
这提供了一个可以处理回调和简单命令的函数。对于更复杂的命令,提供一个回调函数,它会被每个参数依次调用。回调函数可以任意复杂,但请记住,因为它在 setlocal 内运行,所以对环境变量的更改无法转回给调用者。
作为一种解决方法,它允许 一个 变量 escapee 转义范围 - 如果需要,您还可以添加更多。
对于只需要将参数放在末尾的简单命令(如echo),您可以执行相同的操作。它不需要回调函数,但仅限于非常简单的场景。
另外请记住,虽然这看起来有很多代码,但其中绝大多数只需要存在于一个地方。要使用它,您只需要像示例这样的单线:
call :doFor echo my hovercraft is full of eels
还请记住,即使使用此方案,也可能有 other 个字符表现不佳。它解决了? 问题,但其他问题仍可能导致问题。我怀疑这将是一个将 PowerShell 添加到您的简历的理想机会,例如,一个几乎类似于 bash 的命令,其优雅和禅意:
PShell> foreach ($item in @("1", "?", "3", "4")) { echo $item }
1
?
3
4