Search code examples
powershellbatch-filerobocopyxcopy

Batch File to copy files to new directory while renaming, skipping existing files, and without confirmation


I am creating a batch file to be run later which will be used to copy files from one location to another while renaming the files, skipping any existing files, and without prompting the user. Examples of files to be copied:

00021001.txt
00021001.xyz
00021001.abc
00021001001.jpg

Copied files will have the names:

00022001.txt
00022001.xyz
00022001.abc
00022001001.jpg

Things I have tried:

xcopy C:\Testing\1000012\21\00021*.* C:\Testing\1000013\22\00022*.* /D 

This almost does it. It copies all the files starting with "00021" in the first location into the second location while properly renaming them to start with "00022". It skips all the files with the same name and date stamp, but ends up prompting to copy any files from the source which are newer than the target.

robocopy C:\Testing\1000012\21\ C:\Testing\1000013\22\ 00021*.* /xo /xn /xc

I was hoping that by excluding older, newer, and same date files it would work (even if it doesn't rename - I would just do that in a separate step.) Unfortunately, this just ends up overwriting newer source files over existing target files if they are a different filesize.

I have even tried the Copy-Item command in PowerShell. But it doesn't do the renaming like Xcopy, and it doesn't skip existing files (although I can get it to confirm and say "No to All".)

Copy-Item -Path "C:\CWUImageCompare\Testing\1000012\CWU\chemistry\129\21\00021*.*" -Destination "C:\CWUImageCompare\Testing\1000013\CWU\chemistry\129\20\" -Confirm

If xcopy had the "Skip if existing" flag I'd be all set, but it doesn't.


Solution

  • @ECHO OFF
    SETLOCAL ENABLEDELAYEDEXPANSION 
    rem The following settings for the source directory & destination directory are names
    rem that I use for testing and deliberately includes spaces to make sure
    rem that the process works using such names. These will need to be changed to suit your situation.
    
    SET "sourcedir=u:\your files"
    SET "destdir=u:\your results"
    FOR /f "skip=1delims=" %%b IN ('xcopy /L /Y "%sourcedir%\00021*.*" "%destdir%\00022*.*" ^|sort') DO (
     SET "oname=%%~nxb"
     IF EXIST "%destdir%\00022!oname:~5!" (ECHO "%%b" skipped) ELSE (ECHO COPY /y "%%b" "%destdir%\00022!oname:~5!")
    )
    GOTO :EOF
    

    Always verify against a test directory before applying to real data.

    Seems a little complicated, but essentially, execute the xcopy (I omitted the /D for testing) with /L /Y to simply produce a list.

    Since the list has a last line that begins with a numeric, whereas the other lines start with a drive-letter, sort the list and skip the first line.

    This would implement the date-requirement.

    Then grab the part after the first 5 characters of the name+extension, test whether the new name exists and either report or copy as appropriate (The copy command is disarmed for testing)