Windows – Move multiple files from subfolders to one folder using CMD or Batch

batchcommand linewindows

I have files in subfolders which are in a folder structure is like this:

D:\Folder_Source  
D:\Folder_Source\file1.txt  
D:\Folder_Source\FolderA  
D:\Folder_Source\FolderA\file1.txt  
D:\Folder_Source\FolderA\file2.txt  
D:\Folder_Source\FolderB  
D:\Folder_Source\FolderB\file3.txt  
D:\Folder_Source\FolderB\file4.txt  
D:\Folder_Source\FolderB\file8.txt

I want to move some txt files in each subfolder to C:\Destination\ from a command prompt.

For example, the files I want to move are file1.txt, file2.txt, file8.txt, etc.

If there is a file in the destination folder with the same name of the file from the source folder being copied, I want to keep both files and not overwrite the existing file.

I tried this which fails and does not give me the expected result:

move /s file1.txt file2.txt file8.txt C:\Destination

Is something like this even possible from command line or a batch script?

Best Answer

You can use a batch script and set three variables in it with one being the path to the root source directory which will be traversed for specific files, the second being the destination path where the new files will be copied, and the third being a file list of the file names you wish to copy to the destination directory.

With these three variables you can use a FOR /R loop to traverse the source location and use conditional IF logic to check whether or not files already exist for whatever copy or delete operation needs to be performed with each file. Furthermore you can use a CALL and variable substitutions to pass the parts of the file name to another routine and use additional IF logic along with SET /A to increment the duplicate file number, etc.


Batch Script

@ECHO OFF

SET "source=C:\Folder_Source"
SET "dest=C:\Destination"
SET "FileList=file1.txt file2.txt file8.txt" 

SET "dupCnt=1"

FOR /R "%source%" %%A IN (%FileList%) DO (
    IF NOT EXIST "%dest%\%%~NXA" (
        XCOPY /F /Y "%%~FA" "%dest%\" && IF EXIST "%%~FA" DEL /Q /F "%%~FA"
    ) ELSE (
        CALL :DupeRoutine "%%~FA" "%%~NA" "%%~XA"
        )
    )
GOTO :EOF

:DupeRoutine
IF EXIST "%dest%\%~2_(%dupCnt%)%~3" (
    SET /A dupCnt=%dupCnt%+1
    CALL :DupeRoutine "%~1" "%~2" "%~3"
) ELSE (
    IF NOT EXIST "%dest%\%~2_(%dupCnt%)%~3" ECHO F | XCOPY /Y /F "%~1" "%dest%\%~2_(%dupCnt%)%~3" && DEL /Q /F "%~1"
    SET "dupCnt=1" 
    )
GOTO :EOF

Results

Note: If you wish for the duplicate file names to use another naming convention than the _(#) I used then you will need to change the _(%dupCnt%) in the script within "%dest%\%~2_(%dupCnt%)%~3" to be whatever other format you wish to use but %dupCnt% is the number that will increment. I'm happy to help further with this too.

Source Before

D:\Folder_Source
│   file1.txt
│   file2.txt
│   file4.txt
│   file8.txt
│   file99.txt
│
├───FolderA
│       file1.txt
│       file2.txt
│       file4.txt
│       file8.txt
│       file99.txt
│
└───FolderB
        file1.txt
        file2.txt
        file4.txt
        file8.txt
        file99.txt

Destination After

C:\Destination
    file1.txt
    file1_(1).txt
    file1_(2).txt
    file2.txt
    file2_(1).txt
    file2_(2).txt
    file8.txt
    file8_(1).txt
    file8_(2).txt

Source After

D:\Folder_Source
│   file4.txt
│   file99.txt
│
├───FolderA
│       file4.txt
│       file99.txt
│
└───FolderB
        file4.txt
        file99.txt

Further Resources

  • FOR /R
  • IF
  • XCOPY
  • DEL
  • CALL

  • Batch Substitutions (FOR /?)

    In addition, substitution of FOR variable references has been enhanced. You can now use the following optional syntax:

    %~I         - expands %I removing any surrounding quotes (")
    %~fI        - expands %I to a fully qualified path name
    %~nI        - expands %I to a file name only
    %~xI        - expands %I to a file extension only
    
  • SET

    Arithmetic expressions (SET /a)

    Placing expressions in "quotes" is optional for simple arithmetic but required for any expression using logical operators.

    Any SET /A calculation that returns a fractional result will be rounded down to the nearest whole integer.

    The expression to be evaluated can include the following operators:

    + Add set /a "_num=_num+5"

Related Question