Larry
Larry

Reputation: 183

Copy files from first level subfolder only to another location

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

Answers (2)

aschipfl
aschipfl

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

JosefZ
JosefZ

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

Related Questions