I have a script that extracts all files from all sub-directories and deletes the empty sub-directories afterwards, the part that extracts reads:
for /r %%a in (*.*) do move "%%a" "%~dp0"
Is there a way to do this with the exception of sub-directories named "_Unsorted"? I know xcopy has an /exclude
option, so something like
for /r %%a in (*.*) do xcopy "%%a" "%~dp0" /exclude "\_Unsorted\"
would almost work, but I'm not sure how to delete the original after it's copied to essentially have the same result as move
Some batch-only options:
Add a filter into the loop body:
for /r %%a in (*.*) do (
(echo %%~dpa | find /i "\_Unsorted\" 1>nul) || move "%%a" "%~dp0"
)
Alternatively:
for /r %%a in (*.*) do (
(echo %%~dpa | find /i /v "\_Unsorted\" 1>nul) && move "%%a" "%~dp0"
)
In both versions, the find
command is used to match the file's path against the substring \_Unsorted\
. In the first version, find
returns success
if there is a match and fail
otherwise. The move
command is called only in case of fail
, which is the effect of the ||
operator`.
In the second version, the /v
switch reverses the result of find
and success
now means no match. Accordingly, the &&
operator is used to call move
in case of success
.
Apply the filter to the file list, so that the loop never iterates over _Unsorted
entries.
for /f "delims=" %%a in (
'dir /s /b ^| find /i /v "\_Unsorted\"'
) do move "%%a" "%~dp0"
This is a more essential change to the original script than the previous option, as this replaces the for /r
loop with a for /f
one.
Basically, a for /f
loop is used to read/parse a piece of text, a text file or a command's output. In this case, the dir
command provides a complete list of files in the current directory's tree and the find
command filters out those containing \_Unsorted\
in their paths. The for /f
loop reads the list after it's been filtered down by find
, which means it never hits files stored in _Unsorted
(sub)folders.