Reputation: 183
I want to copy all files in only second level subfolders to another location. All file names are unique. The second level subfolders in this example are 01102009, 05302009, and 09012010. Example:
C:\test\
2009\
01102009\
file123.A09
file567.B07
05302009\
fileabc.A09
filexyz.A09
ThirdLevelSubFolder\
fileBLAH.B10
2010\
09012010\
fileHello.A08
fileBye.B10
etc.
Should return:
C:\final\
file123.A09
file567.B07
fileabc.A09
filexyz.A09
fileHello.A08
fileBye.B10
Notice it did not copy fileBLAH.B10 which was in a third level subfolder.
If it helps, all files end in .A## or .B##, where ## is a two digit number.
I tried this:
robocopy "C:\test" "C:\final" s /LEV:2
but that copies over the second level folders (e.g., 01102009) and the files inside them. I just want the files.
I also tried:
for /r "C:\test" %i in (*.*) do copy "%~fi" "C:\final"
but that copies files in all subfolders, including third level ones, whereas I want only files in the second level subfolders.
Upvotes: 1
Views: 2695
Reputation: 34899
The trick is two nested for /D
loops, each covering a certain directory hierarchy level:
@echo off
for /D %%A in ("C:\test\*") do (
for /D %%B in ("%%~fA\*") do (
xcopy /L /I "%%~fB\*.*" "C:\final"
)
)
This code does actually not copy anything, it just lists what would be copied; to enable copying, remove the /L
switch from xcopy
.
The script does not filter against patterns *.A??
and *.B??
; if you want to do so, you will need two xcopy
commands.
Further, it does not copy anything from the first directory level as your sample listing does not show any files there.
Amendment:
When I'm talking about directory levels, I consult the following definition:
All levels are numbered relatively to the root location C:\test\
, so 2009\
is the 1st level, 01102009\
is the 2nd one, and so on.
Upvotes: 1
Reputation: 30113
Final edit according to foxidrive's comment. You need two nested loops to treat files in the second level subfolder (although aschipfl's solution with for /D
may be a bit more concise):
for /F "delims=" %I in ('dir /B /A:D "C:\test\*.*"') do @for /F "delims=" %i in ('dir /B /A:D "C:\test\%~I\*.*"') do @echo copy /B "C:\test\%~I\%~i\*.*" "C:\final\*.*" 2>NUL
Original answer:
for /r
= Loop through files (Recurse subfolders); try (not recursing) dir /B
in
FOR /F
= Loop command: against the results of another command instead as follows:.
for /F "delims=" %i in ('dir /B /A:D "C:\test\*.*"') do copy /B "C:\test\%~i\*.*" "C:\final\*.*" 2>NUL
Note that 2>NUL
prevents displaying of the The system cannot find the file specified
message if source folder is empty.
Output (with changed C:\
to D:\
): The first dir /B
shows that we start with the target folder empty, while the last dir /B
shows that the target was populated with copied files...
d:\bat>dir /B "d:\final\*.*"
d:\bat>for /F "delims=" %i in ('dir /B /A:D "d:\test\*.*"') do @copy /B /Y "d:\test\%~i\*.*" "d:\final\*.*" 2>NUL
d:\test\31441809\ttt.txt
1 file(s) copied.
d:\test\ProcMon\LogfileAcrord32Start.CSV
d:\test\ProcMon\LogfileIE.CSV
d:\test\ProcMon\LogfileIEStart.CSV
d:\test\ProcMon\LogfileSwriter.CSV
d:\test\ProcMon\LogfileSwriterStart.CSV
5 file(s) copied.
d:\test\ScreenCaptures\*.*
0 file(s) copied.
d:\test\set\HKCU.txt
d:\test\set\hklm.txt
d:\test\set\regs.txt
d:\test\set\set.txt
d:\test\set\t!exclam!t.txt
5 file(s) copied.
d:\bat>dir /B "d:\final\*.*"
HKCU.txt
hklm.txt
LogfileAcrord32Start.CSV
LogfileIE.CSV
LogfileIEStart.CSV
LogfileSwriter.CSV
LogfileSwriterStart.CSV
regs.txt
set.txt
t!exclam!t.txt
ttt.txt
d:\bat>
Upvotes: 1