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.
What happens when the content of the enumerated directory (tree) is changed by the command(s) in the body of the for
command?
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?
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
?
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?
Note:
See also my similar question about the forfiles
command.
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). ;)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With