At which point does `for` or `for /R` enumerate the directory (tree)?
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.
What happens when the content of the enumerated directory (tree) is changed by the command(s) in the body of the
Supposed we have the directory
D:\data with the following content:
file1.txt file2.txt file3.txt
The output of
for %F in ("*.txt") do echo %F when executed in said directory will reflect the above list obviously.
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 behave in that context? Supposed there are several sub-directories
sub3, each containing the above list of files;
for /R is currently iterating through
sub1 has already been processed, but
sub3 not yet; the contents of
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
Finally, is there a difference in behaviour of
for /R when being executed in the command prompt or from a batch file? And are there differences in different Windows versions?
See also my similar question about the
This is an excellent question!
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 )
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 )
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.
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).
Answered By – Aacini