3

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?

Vomit IT - Chunky Mess Style
  • 40,038
  • 27
  • 84
  • 117

1 Answers1

3

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"

Vomit IT - Chunky Mess Style
  • 40,038
  • 27
  • 84
  • 117
  • @LutfiCreativesys I used a combination of `XCOPY` & `DEL` rather than `MOVE` since I could put some validation conditional logic in with that command too. Also note that when you move, files will retain NTFS ACL attributes whereas when you use `XCOPY` it inherits the ACL attributes from the location which the files are copied. Typically you want to handle file security at a folder level so that is another reason I prefer `XCOPY` over `MOVE` although I used `Robocopy` a lot too, I usually don't keep dupes like this though either. Let me know if I can adjust further to accommodate your needs. – Vomit IT - Chunky Mess Style Jan 23 '19 at 22:11
  • 1
    Nice answer guy – Tim_Stewart Feb 07 '19 at 19:21
  • 1
    lol regrettably, currently doing Telco contracting. Looking for full-time I.T employment. – Tim_Stewart Feb 07 '19 at 20:10
  • why when I enter a file list of more than 500, the script doesn't work? – Lutfi Creativesys Feb 11 '19 at 05:09
  • Does the script have limits on move files? – Lutfi Creativesys Feb 11 '19 at 05:09
  • @LutfiCreativesys It's likely a batch limit but I'm not sure without researching it. You could try having two smaller arrays maybe and iterate those within another loop one after the other perhaps. Or use a filelist from a file as I wrote about in this answer https://superuser.com/questions/1267964/a-cmd-batch-for-f-command-that-will-not-open-a-text-file/1269852#1269852 where the text file contains the list of file you want to copy or whatever. Smells like justification for you to start a new question potentially for a more definitive answer. Q&A power to the rescue!! – Vomit IT - Chunky Mess Style Feb 11 '19 at 05:35