Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
888 views
in Technique[技术] by (71.8m points)

batch file - At which point does `for` or `for /R` enumerate the directory (tree)?

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.

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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). ;)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...