There are several problems:
- Since you are trying to move directories, the directory tree enumerated by
for /R
is modified. for
/for /R
however does not enumerate the directory (tree) in advance, therefore unexpected results may occur -- see the following question for details about that: At which point does for
or for /R
enumerate the directory (tree)?.
for
or for /R
accesses the file system only in case there are wildcards given in the set (that is the part in between parentheses).
- It is not perfectly clear what exactly you want to accomplish:
- what should happen in case of conflicting items? overwrite them or not? merge (sub-)directories?
- in case of
E:\TEST\TEST
, do you want E:\TEST
to be moved at once, so there is no more directory TEST
at E:\
?.
- Note that the
move
command cannot be used because it causes trouble when moving directories and the destination directory already exists (Access is denied.
errors occur).
Item 1. can be solved by a nice work-around using for /F
and dir
:
for /F "eol=| delims=" %%I in ('dir /B /S /A:D "E:\TEST"') do echo(%%I
This enforces the entire directory tree to be enumerated (read) before the loop iterations start.
However, this introduces another problem similar to item 2.: when a name is given for dir
that matches a directory existing in the given location, its content is returned rather than all items matching that name. What I mean is the following:
dir /B /S /A:D "E:\"
returns all directories (/A:D
) at E:\
recursively (/S
);
dir /B /S /A:D "E:\file.ext"
returns all directories called file.ext
, even if there is a file named E:\file.ext
;
- but:
dir /B /S /A:D "E:\TEST"
returns all sub-directories of E:\TEST
, but not E:\TEST
itself;
- however:
dir /B /S /A:D "E:\TEST*"
returns all directories beginning with TEST
, also those in E:\
; to exactly match the name TEST
, additional filtering is required (using findstr
);
All this means:
for /F "eol=| delims=" %%I in ('dir /B /S /A:D "E:\TEST*" ^| findstr /I /E /C:"\\TEST"') do echo(%%I
Item 3. can only be solved by you, but to provide a complete answer, I make some assumptions:
- (sub-)directories are merged, already existing items are overwritten without notice;
- parent directories take precedence over sub-directories (like
for /R
and dir /S
behave, because for every branch in a tree, they always go from higher down to lower directory levels);
Item 4. can be solved by using command robocopy
together with option /MOVE
instead of move
.
So here is the final script:
@echo off
rem // Define constants here:
set "_PATH=E:\"
set "_NAME=TEST"
set "_DEST=E:\FOUND"
2> nul mkdir "%_DEST%"
for /F "eol=| delims=" %%I in ('
dir /B /S /A:D "%_PATH%\%_NAME%*" ^| findstr /I /E /C:"\\%_NAME%"
') do (
> nul robocopy "%%I" "%_FOUND%\%_NAME" /E /MOVE
)
The > nul
portion is intended to suppress progress and log messages and to suppress The system cannot find the path specified.
errors in case E:\TEST\TEST
is attempted to be moved although it does no longer exist since the parent E:\TEST
has alread been moved before.