3

我编写了以下批处理文件来使用 FOR 循环创建多个文件:

@echo 关闭  
分类  
FOR /L %%i IN (1 1 10) DO (  
    echo.> 文件%%i.txt  
    IF ERRORLEVEL 0 echo 成功创建文件'file%%i.txt'。  
)  
目录 /b *.txt  
FOR %%i IN (*.txt) DO (  
    echo.> 文件%%i.txt
    IF ERRORLEVEL 0 echo 成功创建文件'file%%i.txt'。  
)

在这里,在第一个 FOR 循环中创建了10 个文件(即file1.txt.... )。 在第二个 FOR 循环中,我使用这些文件来框定下一个新文件的名称。(即…… ) file10.txt
filefile1.txt.txtfilefile10.txt.txt

但是,正在创建一个额外的文件: 什么逻辑问题导致了这个额外文件的创建?filefilefile1.txt.txt.txt

4

3 回答 3

5

已编辑 - 似乎我没有正确解释它,人们没有看到它是如何工作的。我的错。我将尝试更好地解释它。

原因是 for 命令在内部工作的方式。

到达该行时for var in (files),将检查目录以查看是否有任何文件匹配并需要处理。

然后,for命令(实际上是 cmd)发出目录查询以枚举文件。此查询仅返回集合中的第一个文件。如果有任何附加文件与for命令中的文件掩码匹配,则会设置一个标志,向调用者 (cmd) 指示还有更多文件要处理,但尚未检索到剩余文件的列表

当内部代码for的执行到达迭代结束时,并且有待读取的文件,发送查询以获取待处理的待处理文件列表的剩余for部分,并且与文件选择匹配。

系统用剩余文件列表填充缓冲区。如果此时文件列表足够短,可以在缓冲区中完全读取,则不会重复查询。如果文件列表大到无法放入缓冲区,则检索部分列表,当处理检索列表中的文件时,将再次发送查询以获取更多要处理的文件。

缓冲区中的文件数取决于文件名的长度。更短的文件名,缓冲区中的更多文件以及对文件系统的更少查询。

此行为(在第一个文件处理结束时检索剩余的文件列表)仅在文件查询返回有待处理文件时才会执行。当一个查询未返回该标志时,将不再检索文件。

例外情况

如果在 NTFS 中工作,文件只有在按字母顺序大于for命令中处理的最后一个文件时才会包含在“请求”中。

如果在 FAT 下工作,则查询将包括所有生成的与for命令文件选择匹配的新文件,而与它的名称无关。是的,它可以进入无限循环。(在测试中,系统缓冲区只检索一个文件名,并在每次迭代中重新查询)。你可以试试

break > a.txt && cmd /v:on /c "for %f in (*.txt) do break > !random!.txt"

我所有的测试都是在 Windows 7 64 位、NTFS 和 FAT32 分区(在 USB 驱动器上)上进行的。没有办法测试其他配置。如果有人看到不同的行为,请发表评论。

更多信息,ZwQueryDirectoryFile

于 2013-10-31T11:43:06.597 回答
3

我不知道为什么,但是当您... IN (*.txt) ...在第二个for循环中编写时,它会尝试查找刚刚在循环体内创建的文件。

为了消除这种情况,我会让我的过滤器更具体一些。

FOR %%i IN (file??.txt) DO (

我运行了它,它只按预期创建了 20 个文件。

于 2013-10-31T11:23:06.183 回答
3

就像 adarshr 所说,第二个 FOR 循环甚至可以找到新创建的文件。
您可以通过将 FOR/F 与命令一起使用来避免这种情况,因为在执行循环体之前已完全获取 dir 的结果。

...
FOR /F "delims=" %%i IN ('dir /b *.txt') DO (  
    echo.> file%%i.txt
    IF ERRORLEVEL 0 echo Successfully created file 'file%%i.txt'.  
)
于 2013-10-31T11:28:09.577 回答