Monday, July 6, 2015

windows - Bulk File Rename and Move


I am looking for a Windows/Dos based method to rename and copy/move files based on a CSV import file contents.


For example:


Import file example:
"C:\Dir1\File001.txt","Q:\Dir02\Dir03\Dir04\NewFile001.txt"
"C:\Dir2\File002.txt","Q:\Dir05\Dir06\Dir07\NewFile002.txt"
"C:\Dir3\File003.txt","Q:\Dir08\Dir09\Dir10\NewFile003.txt"

What I need


Ideally the method would take the above as input and copy/move files from Column 1 to Column 2 while creating any necessary directories.


I'm also looking for some error handling such as



  • Can't create directory / folder (for whatever reason)

  • File Already Exists - either at the destination or because the rename input puts two files with the same name in the same directory.

  • Have a way to deal with collisions (add suffix, etc).


What I've tried


I've tried the following apps so far but have not been able to get them to work as I need so wanted to see if there's a different method rather than software that'll do this sort of operation with Windows:



  1. Bulk Rename Utility



    • Tried to use the "Import Pairs" function but got no results. (Literally nothing happens with no errors.)


  2. Advanced Renamed



    • Can import my load file, but it only uses the file names from Column 2. Doesn't move the files into the folders.


  3. Dos Batch using move or copy



    • Existing files get overwritten, the error messages for long paths/filenames are non descriptive, no error correction for duplicate filenames.



    • My batch copy



      • COPY /Y "C:\Dir1\File001.txt" "Q:\Dir02\Dir03\Dir04\NewFile001.txt"





Any other suggestions or methods that will work and suffice for all my needs if possible would be greatly appreciated since everything I have tried comes up short of the expected result for the specified reasons so I was curious if someone on SuperUser can help me with this task.


Answer



Using some simple FOR /F logic and by setting the delimiters and the tokens accordingly, you can parse thru each line of the csv file and use each comma separated value as a variable to process accordingly per each loop iteration.


With some simple conditional IF logic, you can control which commands to run based on each condition being TRUE or FALSE but this is where it can check whether or not files already exist or not, and take action accordingly.


Using the XCOPY command with a piped ECHO F tells it that each parameter passed to it is a file and not a directory, and if any directory does not exist anywhere along the path where the file is copied to (e.g. column 2), all will be created during the file copy operation.


If the destination file already exist and you wish to append a unique suffix to each file name copied that has a matching file name in the destination directory, you can use simple CALL logic passing each FOR /F loop variable as an argument to a routine.


You can use substitutions to parse out different portions of the passed CALL variables to reconstruct and append the unique string as a suffix to any existing destination files.





Essentially this will. . .



  1. Use the comma as a delimiter with the FOR /F loop and get each value from the csv file separated by each delimiter to use individually for further processing

  2. If the source file from column 1 does not exist, quit and then process the next csv line

  3. If the destination file from column 2 does exist, call a routine and pass the two csv file line values to that routine as variables to expand and process
    further



    • This routine will create a unique string using date time and ensure this is appended to the destination
      file name that is copied over ensuring the existing file is not
      overwritten by the copy operation


  4. If both the destination file does not exist and the source file does exist, it'll simply copy over the file from the source to the
    destination


  5. If none of these conditions are TRUE, then it does nothing with the iterated csv file values from those lines.






Batch Script


@ECHO ON
SET csvfile=C:\Users\User\Desktop\test.csv
FOR /F "USEBACKQ TOKENS=1,2 DELIMS=," %%a in ("%csvfile%") DO (
IF NOT EXIST "%%~a" GOTO :EOF
IF EXIST "%%~b" CALL :DupeRoutine "%%~a" "%%~b"
IF NOT EXIST "%%~b" IF EXIST "%%~a" ECHO F | XCOPY /Y /F "%%~a" "%%~b"
)
GOTO :EOF
:DupeRoutine
::: --Use this with system DATE format "Fri 10/13/2017"
::SET tstamp=%date:~10%%date:~4,2%%date:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%%time:~9,2%
::: Use this with system DATE format "2017-10-13"
SET tstamp=%date:~0,4%%date:~5,2%%date:~8,2%_%time:~0,2%%time:~3,2%%time:~6,2%%time:~9,2%
SET tstamp=%tstamp: =0%
ECHO F | XCOPY /Y /F "%~dpnx1" "%~dp2%tstamp%%~n2%~x2"
GOTO :EOF

Note: If you wish to delete the source files once the file is copied to the destination, you can make some slight adjustments with this example batch script using further conditional logic such && DEL /Q /F appended to the applicable commands where copy operations complete.




Further Resources



  • FOR /F

  • IF

  • CALL


    HELP CALL
    Substitution of batch parameters (%n) has been enhanced. You can
    now use the following optional syntax:
    %~1 - expands %1 removing any surrounding quotes (")
    %~d1 - expands %1 to a drive letter only
    %~p1 - expands %1 to a path only
    %~n1 - expands %1 to a file name only
    %~x1 - expands %1 to a file extension only

  • XCOPY



No comments:

Post a Comment

linux - How to SSH to ec2 instance in VPC private subnet via NAT server

I have created a VPC in aws with a public subnet and a private subnet. The private subnet does not have direct access to external network. S...