Copying files between two similar, but not matching, directory trees

Viewed 54

I have a source directory structure and a destination directory structure. The destination directory structure is a sub-set of the source directory structure. That is, in the destination directory structure certain sub-folders are not present.

I want to copy certain files, lets say *.jpg, from the source to the destination and I don't want to create the missing folders at the destination. I think, for this reason I cannot use robocopy or xcopy as they would re-create the source-structure at destination when using the /S /E switches.

So the situation looks like:

source
  folder1
    subfolder1
      file1.jpg
  folder2
    file2.jpg
  folder3
    file3.jpg
destination (before copying)
  folder1
    subfolder1
  folder3
destination (after copying)
  folder1
    subfolder1
      file1.jpg
  folder3
    file3.jpg

I tried using something like this:

@echo off
setlocal EnableDelayedExpansion
set src_dir=l:\DP\
set dest_dir=l:\test

for /R "%src_dir%" %%x in (*.jpg) do (
    copy "%%x" "%dest_dir%\%%x"
)

I am pretty sure the problem is with "%dest_dir%\%%x" but no idea how to fix it. The English translation of the error message I get is "The syntax for the file, directory or drive is wrong."

Thanks for your help in advance!

1 Answers

Unfortunately, there is no switch for xcopy or robocopy that prevents it from creating directories.

Anyway, here is a script that accomplishes your task in a flexible manner (see the rem remarks):

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define constants here:
set "_SOURCE=%~dp0source"      & rem // (full path to source directory)
set "_TARGET=%~dp0destination" & rem // (full path to target directory)
set "_MASKS=*.jpg"             & rem // (`|`-separated list of patterns)
set "_MODE=A"                  & rem // (see below for possible modes)
set "_DIRS="                   & rem // (if empty, do not create sub-direcories)

rem // Resolve mode setting:
if /I "%_MODE%"=="A" (           rem // (`A`ll, copy new, overwrite existing)
    set "OPT=/-Y"
) else if /I "%_MODE%"=="R" (    rem // (`R`enew, copy new, overwrite older)
    set "OPT=/D"
) else if /I "%_MODE%"=="N" (    rem // (`N`ew, copy new, maintain existing)
    set "OPT= "
) else if /I "%_MODE%"=="P" (    rem // (re`P`lace, skip new, overwrite existing)
    set "OPT=/U"
) else if /I "%_MODE%"=="U" (    rem // (`U`pdate, skip new, overwrite older)
    set "OPT=/D /U"
) else exit /B 1

rem // Ensure that target directory exists:
mkdir "%_TARGET%" 2> nul & pushd "%_TARGET%" && (
    rem // Change into source directory:
    pushd "%_SOURCE%" && (
        rem // Resolve list of file name patterns and loop through them:
        setlocal EnableDelayedExpansion
        for /F "eol=| delims=" %%M in (^"!_MASKS:^|^=^
%= mandatory blank line, do not (re-)move! =%
!^"        ) do (
            if "!!"=="" endlocal
            rem // Loop through applicable file paths relative to source directory:
            for /F "tokens=1* delims=:" %%E in ('
                xcopy "%%~M" "%_TARGET%" /L /E /I %OPT:/U=% /Y
            ') do (
                set "FLAG=#" & if "%%F"=="" set "FLAG="
                rem // Check whether target sub-directory and file already exists:
                if not exist "%_TARGET%\%%F\.." (
                    if defined _DIRS (md "%_TARGET%\%%F\..") else set "FLAG="
                )
                if "%OPT%"==" " if exist "%_TARGET%\%%F" set "FLAG="
                if not "%OPT:/U=%"=="%OPT%" if not exist "%_TARGET%\%%F" set "FLAG="
                rem // Actually copy current file:
                if defined FLAG copy /Y "%%F" "%_TARGET%\%%F" > nul
            )
        )
        rem // Return from source directory:
        popd
    )
    rem // Return from target directory:
    popd
)

endlocal
exit /B
Related