简体   繁体   中英

How to copy the contents of all subdirectories into one directory, retaining structure and overwriting duplicates with a batch file?

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 :)

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM