The command forfiles
is intended to enumerate a directory and apply (a) certain command(s) on each item. With the /S
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 forfiles
command?
Supposed we have the directory D:\data
with the following content:
file1.txt
file2.txt
file3.txt
The output of forfiles /P "D:\data" /M "*.txt" /C "cmd /C echo @file"
when executed in said directory will reflect the above list obviously.
However, what is the output of forfiles
when a command in the 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 forfiles /S
behave in such a situation? Supposed there are several sub-directories sub1
, sub2
, sub3
, each containing the above list of files; forfiles /S
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
?
I am mainly interested in the behaviour of forfiles
since Windows Vista.
Note:
I already posted a very similar question about the for
command. However, since forfiles
is not a built-in command and has got a completely different syntax I decided to post a separate question instead of extending the scope of the other one.
forfiles
will fail to continue enumeration of a renamed folder with an ERROR: The system cannot find the file specified.
once you try to use a @-variable which resolves to a nonexistent file. There'll be no error for a deleted file and it will see a newly added file if its name follows the currently processed one in currently used order of enumeration (I've tested it with default alphabetic sort in ascending order). So evidently it doesn't build the entire list of files prior to execution of the command but enumerates them one by one after the custom command completes.
Depending on what exactly you need to do with forfiles
the reliable solutions would be parsing the output of dir /s /b
or of robocopy
in a list-only mode. Thus you can ensure the list is generated prior to any change.
for /f "delims=" %%a in ('dir "d:\data\*.txt" /s /b') do .......
Suitable for simple enumerations
for /f "tokens=*" %%a in ('robocopy /L /njh /njs /ndl ........') do ...
Suitable for more complicated scenarios like limiting the date span, may require using additional parsing and /v
in non-straightforward cases.