至于参考资料,SS64.com也不错。Rob van der Woude也经常被联系起来。
至于你的问题,这很简单:
@echo off
setlocal enableextensions enabledelayedexpansion
set LIST=
for /f %%x in (yourfile.txt) do (
set LIST=!LIST! "%%x"
)
echo %LIST%
endlocal
更深入的解释:
setlocal enableextensions enabledelayedexpansion
我们在这里启用延迟扩展。这是至关重要的,否则我们将无法在随后的for
循环中操作文件列表。
for /f %%x in (yourfile.txt) do (
set LIST=!LIST! "%%x"
)
for /f
遍历文件中的行,这正是我们需要的。在每次循环迭代中,我们将下一行附加到LIST
变量中。注意使用 of!LIST!
而不是通常的%LIST%
. 这表示扩展延迟,并确保每次运行此命令时都会重新评估变量。
通常cmd
在读取和解析一行后立即将变量扩展为它们的值。对于cmd
单行来说,要么是一行,要么是所有算作一行的东西,这恰好适用于由括号分隔的块,就像我们在这里使用的那样。因此,cmd
对于完整的块来说,无论循环内部运行的频率如何,它都会被读取和解析一次。
如果我们在%LIST%
这里使用而不是!LIST!
then 变量将立即被其值替换(此时为空),循环将如下所示:
for /f %%x in (yourfile.txt) do (
set LIST= "%%x"
)
显然这不是我们想要的。延迟扩展确保仅在真正需要其值时才扩展变量。在这种情况下,当循环内部运行并构造文件名列表时。
之后变量%LIST%
或!LIST!
(现在使用哪个不再重要)包含文件中的行列表。
有趣的是,该set
命令的帮助正好包括这个延迟扩展的例子:
最后,添加了对延迟环境变量扩展的支持。默认情况下始终禁用此支持,但可以通过 /V 命令行开关到 CMD.EXE 启用/禁用。见 CMD /?
延迟的环境变量扩展对于绕过当前扩展的限制很有用,这种限制发生在读取一行文本时,而不是在执行时。以下示例演示了立即变量扩展的问题:
set VAR=before
if "%VAR%" == "before" (
set VAR=after
if "%VAR%" == "after" @echo If you see this, it worked
)
永远不会显示该消息,因为 BOTH IF 语句中的 %VAR% 在读取第一个 IF 语句时被替换,因为它在逻辑上包括 IF 的主体,这是一个复合语句。因此,复合语句中的 IF 实际上是将“之前”与“之后”进行比较,这永远不会相等。同样,以下示例将无法按预期工作:
set LIST=
for %i in (*) do set LIST=%LIST% %i
echo %LIST%
因为它不会在当前目录中建立文件列表,而是将 LIST 变量设置为找到的最后一个文件。同样,这是因为在读取 FOR 语句时 %LIST% 只扩展了一次,而此时 LIST 变量为空。所以我们正在执行的实际 FOR 循环是:
for %i in (*) do set LIST= %i
它只是将 LIST 设置为找到的最后一个文件。
延迟环境变量扩展允许您在执行时使用不同的字符(感叹号)来扩展环境变量。如果启用了延迟变量扩展,则上述示例可以编写如下以按预期工作:
set VAR=before
if "%VAR%" == "before" (
set VAR=after
if "!VAR!" == "after" @echo If you see this, it worked
)
set LIST=
for %i in (*) do set LIST=!LIST! %i
echo %LIST%