为什么在批处理程序的FOR循环中创建额外的文件?

时间:2013-10-31 10:56:37

标签: shell batch-file for-loop createfile

我编写了以下批处理文件,使用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
导致创建此额外文件的逻辑问题是什么?

3 个答案:

答案 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'.  
)