0

I am trying to copy thousands of image files listed in a text file from multiple folders to one folder. The script I have works if all the file names were different. How do I get it to rename duplicates or rename all of them? Either will work as the name isn't important.

Example list

G:\research_data\an\an01\DCIM\100MSDCF\DSC04450.JPG
G:\research_data\an\an01\DCIM\100MSDCF\DSC04076.JPG
G:\research_data\an\an01\DCIM\100MSDCF\DSC03141.JPG
G:\research_data\an\an01\DCIM\120MSDCF\DSC04840.JPG
G:\research_data\an\an02\DCIM\100MSDCF\DSC04450.JPG
G:\research_data\an\an02\DCIM\112MSDCF\DSC04076.JPG
G:\research_data\an\an03\DCIM\102MSDCF\DSC03141.JPG
G:\research_data\an\an03\DCIM\105MSDCF\DSC04450.JPG
G:\research_data\an\an03\DCIM\106MSDCF\DSC04076.JPG

code:

@echo off
for /f "tokens=* delims=" %%a in ('type "L:\an_2017\image_list.txt"') do xcopy /hrkvy "%%a" "L:\an_2017"
pause
brink
  • 111
  • 7

3 Answers3

1

I see the issue you're running into. Looks like you're trying to transfer images from various directories with some containing the same file names. If you wish to keep both files, you could use an FOR statement to read your text file and rename the file at hand to DSC{Count} from 1+.

Using enabledelayedexpansion we can use set /a count += 1 to count up one number and rename %%a to a number. Please keep in mind I'm using %%~xa to get the extension of each file from the textfile. More info here: Parameter Extensions

The script bellow will read all file locations in the image_list.txt file and will copy each item to it's target directory with a new name of DSC1-DSCinfinity based on how many items are in image_list.txt. This avoids any issue's with duplicate names in your text file.

@ECHO OFF
@setlocal enableextensions enabledelayedexpansion

rem configure directories
set "source=L:\an_2017\image_list.txt"
set "target=L:\an_2017"

rem rename files to DSC{Count}
set /a count = 1
for /f "tokens=* delims=" %%a in ('type "%source%"') do (

copy "%%a" "%target%\DSC!count!%%~xa"
set /a count += 1

)

goto :EOF
John Kens
  • 1,615
  • 2
  • 10
  • 28
  • The thing with this script is that it will increment each file with +1. So no matter the name, it will be named file1, somecsv2...someexcelfile90112 etc. rather rename the file only if it already exists in the target dir. – Gerhard Sep 13 '18 at 06:50
  • 1
    File name doesn't matter in this instance. It worked perfectly, thank you for your help John. – brink Sep 13 '18 at 16:35
0

In my example below, I am not using the file as a source for the jpg's, though you can still change that it you want. Instead, I dir /s through your DCIM directory, find all jpg files. Then I test the destination directory to see if the file exists, if it does, I increment it with a (n) at the end, if it does not exist, I just copy the file. This way you will have files without numeric increments (duplciates) It will not add a numeric value to each file. We will only do this for duplicates.

@echo off
setlocal enabledelayedexpansion
set "source=G:\research_data\an\an01\DCIM\"
set "dest=L:\an_2017\"
set /a cnt=0
for /f "tokens=*" %%a in ('dir /S /B /A-D "%source%*.jpg"') do for /f "tokens=*" %%b in ('dir /B "%%a"') do if exist "%dest%\%%b" (
        set "ext=%%~xa"
        set "fname=%%~na"
        if exist "%dest%\!fname!(!cnt!)!ext!" (set /a cnt=!cnt!+1)
        set /a cnt=!cnt!+1
        copy "%%a" "%dest%\!fname!(!cnt!)!ext!"
) else copy "%%a" "%dest%\%%b"
Gerhard
  • 22,678
  • 7
  • 27
  • 43
0
@echo off
setlocal

set "source=L:\an_2017\image_list.txt"
set "target=L:\an_2017"

for /f "delims=" %%A in (%source%) do (
    if not exist "%target%\%%~nxA" (
        copy "%%~A" "%target%\%%~nxA"
    ) else (
        call :index "%%~A" "%target%\%%~nxA" "1"
    )
)

exit /b

:index  source, target, count
setlocal
set /a "cnt=%~3"

if exist "%target%\%~n2(%cnt%)%~x2" (
    call :index "%~1" "%~2" "%cnt%+1"
) else copy "%~1" "%target%\%~n2(%cnt%)%~x2"

The source file is read line by line. If the file is not found in the target folder, then a copy done. If the file is found in the target, then the label :index is called with arguments of source, target and the count of 1.

In the called label, cnt is set the value of the count. If the indexed file is not found in target, then a copy is done. If found in target, calls the label again until the indexed file is not found in target and a copy is done.

If you prefer using type, then replace (%source%) with ('type "%source%"').

Note: The index integer is 1 based and does restart from 1 for indexing and increments until the filename is not in the target.

michael_heath
  • 5,262
  • 2
  • 12
  • 22