Reputation: 585
I have a directory with a bunch of subdirectories, and files beneath those subdirectories (I'm running Windows 10):
C:\MyFolder\Able
C:\MyFolder\Able\Alpha
C:\MyFolder\Able\Manifest
C:\MyFolder\Baker
C:\MyFolder\Baker\Bravo
C:\MyFolder\Baker\Manifest
C:\MyFolder\Charlie
C:\MyFolder\Charlie\Charlie
C:\MyFolder\Charlie\Manifest
C:\MyFolder\Dog
C:\MyFolder\Dog\Delta
C:\MyFolder\Dog\Manifest
I'd like to create a batch file to copy all subdirectories of C:\MyFolder
into a specific folder, retaining directory structure and overwriting all duplicate files, but get rid of the first level subdirectory under C:\MyFolder
like this:
C:\MyFolder\Able\*.* --> C:\NewFolder\*.*
C:\MyFolder\Able\Alpha --> C:\NewFolder\Alpha\*.*
C:\MyFolder\Able\Manifest --> C:\NewFolder\Manifest\*.*
C:\MyFolder\Baker --> C:\NewFolder\*.*
C:\MyFolder\Baker\Bravo --> C:\NewFolder\Bravo\*.*
C:\MyFolder\Baker\Manifest --> C:\NewFolder\Manifest\*.*
C:\MyFolder\Charlie --> C:\NewFolder\*.*
C:\MyFolder\Charlie\Charlie --> C:\NewFolder\Charlie\*.*
C:\MyFolder\Charlie\Manifest --> C:\NewFolder\Manifest\*.*
C:\MyFolder\Dog --> C:\NewFolder\*.*
C:\MyFolder\Dog\Delta --> C:\NewFolder\Delta\*.*
C:\MyFolder\Dog\Manifest --> C:\NewFolder\Manifest\*.*
My initial thought was to use the command "dir /b /s /a:d C:\MyFolder"
to get all the sub-folder names and then use the xcopy
command to get each line and copy the files over, but I just can't seem to make the connection.
Thanks in advance :)
Upvotes: 0
Views: 1115
Reputation: 842
This should work:
@ECHO OFF
SETLOCAL EnableDelayedExpansion
REM **************************************************
SET source_dir=C:\MyFolder
SET target_dir=C:\NewFolder
REM **************************************************
FOR /F "delims=" %%G IN ('DIR /S /B /A:D "%source_dir%"') DO (
SET "folder_name=%%G"
CALL :copy
)
ECHO. & ECHO. & ECHO. & ECHO. & ECHO. & ECHO Done^^!
PAUSE
EXIT
:copy
SET "target_folder_name=!folder_name:%source_dir%\=!"
ECHO !target_folder_name! | FINDSTR /C:"\\" >nul && SET "target_folder_name=!target_folder_name:*\=!" || SET "target_folder_name=."
ROBOCOPY "!folder_name!" "%target_dir%\!target_folder_name!" /IT
EXIT /B
This basically removes the C:\MyFolder\*\
from each folder path and the remaining name, path or .
(if it's a direct sub-folder of C:\MyFolder
) is added to the target_dir
path.
If a path remains you could also shrink this path to only a name and combine all files of all sub-directories into one sub-folder.
For this, simply replace the :copy
bit with this:
:copy
SET "target_folder_name=!folder_name:%source_dir%\=!"
ECHO !target_folder_name! | FINDSTR /C:"\\" >nul || SET "target_folder_name=."
SET "loop_counter=0"
:loop
SET /A "loop_counter=%loop_counter%+1"
IF %loop_counter%==10 (ECHO Error: Could not copy !folder_name! && EXIT /B)
ECHO !target_folder_name! | FINDSTR /C:"\\" >nul && SET "target_folder_name=!target_folder_name:*\=!" && SET /A "counter=%counter%+1" && GOTO loop
ROBOCOPY "!folder_name!" "%target_dir%\!target_folder_name!" /IT
EXIT /B
This adds a loop to remove up to 10 parent directories if any and a loop_counter to prevent an endless loop. Obviously you can have more loops by simply adjusting the 10
in this IF-Statement
: IF %loop_counter%==10
.
Upvotes: 1