我编写了以下批处理文件,使用FOR循环创建多个文件:
@echo off cls FOR /L %%i IN (1 1 10) DO ( echo.> file%%i.txt IF ERRORLEVEL 0 echo Successfully created file 'file%%i.txt'. ) dir /b *.txt FOR %%i IN (*.txt) DO ( echo.> file%%i.txt IF ERRORLEVEL 0 echo Successfully created file 'file%%i.txt'. )
此处,在第一个FOR循环中创建了10个文件(即file1.txt
.... file10.txt
)。
在第二个FOR循环中,我使用这些文件来构建下一个新文件的名称。 (即filefile1.txt.txt
... filefile10.txt.txt
)
但是,正在创建一个额外的文件: filefilefile1.txt.txt.txt
导致创建此额外文件的逻辑问题是什么?
答案 0 :(得分:5)
编辑 - 似乎我没有正确解释它,人们不知道它是如何工作的。我的错。我将尝试更好地解释它。
原因是for命令在内部工作的方式。
当到达行for var in (files)
时,将检查目录以查看是否有任何文件匹配且需要处理。
然后,for
命令(实际上为cmd)发出目录查询以枚举文件。此查询仅返回集合中的第一个文件。如果在for
命令中存在与文件掩码匹配的任何aditional文件,则会设置一个标志,指示调用方(cmd)有更多文件要处理,但列表中剩余文件尚未检索。
当for
内的代码执行到达迭代结束时,并且有待审阅的文件待处理时,会发送一个查询以获取待处理文件列表的剩余要处理并匹配for
文件选择。
系统使用剩余文件列表填充缓冲区。如果此时文件列表足够短,可以在缓冲区中完全重写,则不会重复查询。如果文件列表大到不适合缓冲区,则会检索部分列表,当处理检索到的列表中的文件时,将再次发送查询以获取更多要处理的文件。
缓冲区中的文件数取决于文件名的长度。文件名越短,缓冲区中的文件越多,对文件系统的查询越少。
此行为(在第一次文件处理结束时检索剩余文件列表)仅在文件查询返回有待处理文件时才会执行。当一个查询未返回该标志时,不再检索文件。
EXCEPTIONS
如果在NTFS中工作,如果文件按字母顺序大于在for
命令中处理的最后一个文件,则文件仅包含在“requeries”中。
如果FAT工作,则查询将包括所有生成的与for
命令文件选择无关的所有新文件。是的,它可以进入无限循环。 (在测试中,系统缓冲区仅检索一个文件名,并在每次迭代中重新查询)。你可以尝试
break > a.txt && cmd /v:on /c "for %f in (*.txt) do break > !random!.txt"
我所有的测试都是在Windows 7 64位,NTFS和FAT32分区上完成的(这在USB驱动器上)。无法测试其他配置。如果有人看到不同的行为,请发表评论。
有关详细信息,请ZwQueryDirectoryFile
答案 1 :(得分:3)
我不知道为什么,但是当您在第二个... IN (*.txt) ...
循环中编写for
时,它正在尝试查找刚刚在循环体内创建的文件。
为了消除这种情况,我会使我的过滤器更加具体。
FOR %%i IN (file??.txt) DO (
我运行了它,它只按预期创建了20个文件。
答案 2 :(得分: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'.
)