已编辑 - 似乎我没有正确解释它,人们没有看到它是如何工作的。我的错。我将尝试更好地解释它。
原因是 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