问题描述
命令 for
可用于枚举目录并对每个项目应用 (a) 某些命令.使用 /R
可以为完整的目录树完成相同的操作.
The command for
can be used to enumerate a directory and apply (a) certain command(s) on each item. With the /R
the same can be accomplished for a full directory tree.
当枚举目录(树)的内容被 for
命令正文中的命令更改时会发生什么?
What happens when the content of the enumerated directory (tree) is changed by the command(s) in the body of the for
command?
假设我们有目录D:data
,内容如下:
Supposed we have the directory D:data
with the following content:
file1.txt
file2.txt
file3.txt
for %F in ("*.txt") do echo %F
在上述目录中执行时的输出将明显反映上述列表.
The output of for %F in ("*.txt") do echo %F
when executed in said directory will reflect the above list obviously.
但是,当 for
主体中的命令修改目录内容时,for
循环的输出是什么?例如,列表中的一个文件被删除,比如说file3.txt
,在它实际迭代之前?或者,如果在循环完成之前创建了一个新文件,例如 file4.txt
?
However, what is the output of the for
loop when a command in the for
body modifies the content of the directory? For instance, one of the files in the list is deleted, let's say file3.txt
, before it is actually iterated? Or if a new file is created, like file4.txt
, before completion of the loop?
for/R
在这种情况下的表现如何?假设有几个子目录sub1
、sub2
、sub3
,每个子目录都包含上面的文件列表;for/R
当前正在遍历sub2
,sub1
已经被处理了,但是sub3
还没有;sub1
和 sub3
的内容在那一点发生了变化(当当前遍历 sub2
时);那么将枚举什么?我猜,sub1
内容的变化不会被识别,但是sub3
呢?
How does for /R
behave in that context? Supposed there are several sub-directories sub1
, sub2
, sub3
, each containing the above list of files; for /R
is currently iterating through sub2
, sub1
has already been processed, but sub3
not yet; the contents of sub1
and sub3
are changed at that point (when currently walking through sub2
as mentioned); what will be enumerated then? I guess, the change of the content of sub1
won't be recognised, but what about sub3
?
最后,在命令提示符或批处理文件中执行时 for
或 for/R
的行为是否有区别?并且在不同的 Windows 版本中是否存在差异?
Finally, is there a difference in behaviour of for
or for /R
when being executed in the command prompt or from a batch file? And are there differences in different Windows versions?
注意:
另请参阅我关于 forfiles
命令的类似问题.
推荐答案
这是一个很好的问题!
让我们暂时专注于简单的 for
命令.当用于重命名文件时,有一个与此命令相关的已知错误.例如:
Let's concentrate on plain for
command for a moment. There is a known bug related to this command when it is used to rename files. For example:
set i=0
for %%a in (*.txt) do (
set /A i+=1
ren "%%a" !i!.txt
)
在这种情况下,某些文件经常会被重命名两次,在某些情况下甚至会重命名三次.问题是这种行为取决于一系列未记录的因素,例如原始文件列表中第一个重命名文件的位置以及其他几个点.类似地,如果文件在 for
处理之前被删除,则通常会发出找不到文件"消息(尽管不是所有时间).如果在 for
开始执行后在目录中创建了一个新文件,那么它可能会或可能不会被 for
处理,这取决于(再次) 的一系列因素.避免重命名问题的常用方法是强制 for
命令首先读取整个文件列表,然后然后处理列表:
In this case is frequently that certain files be renamed twice, and even three times in certain cases. The problem is that this behavior depends on a series of factors that are not documented, like the position of the first renamed file inside the list of original files and several other points. Similarly, if a file is deleted before it is processed by the for
, a "File not found" message is usually issued (although not ALL times). If a new file is created in the directory after the for
started execution, then it may or may not be processed by the for
depending (again) on a series of factors. The usual way to avoid the problem with rename is to force for
command to first read the whole list of files and then process the list:
for /F "delims=" %%a in ('dir /B *.txt') do (
set /A i+=1
ren "%%a" !i!.txt
)
这样,可以对磁盘中的文件进行的更改无关紧要:for/F
命令将始终处理原始文件列表.
This way, don't matters the changes that can be made on the files in the disk: the for /F
command will always process the original file list.
for/R
命令也会出现类似的问题,但在这种情况下,出现问题的可能性更大,因为可以进行动态更改的目录更多.同样:确切的行为取决于一系列未知因素,避免它们的方法是通过 for/F ... in ('dir/S/B')
.但是,如果您真的对这一点感兴趣,我鼓励您对该主题进行一系列测试(并发布结果).;)
A similar problem happen with for /R
command, but in this case the possibility of problems is greater because there are more directories where dynamic changes can be made. Again: the exact behavior depends on a series of unknown factors and the way to avoid them is via for /F ... in ('dir /S /B')
. However, if you are really interested in this point, I encourage you to made a series of tests on the subject (and post the results). ;)
这篇关于`for` 或 `for/R` 在哪一点枚举目录(树)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!