0

I have a folder with files and a .txt file with a list of file names and number of copies that I need to copy from one folder to another.

The script is copying the files but if the .txt file has two files of the same name it overwrites the old file.

In the list I have:

file1.txt 1
file2.txt 1
file1.txt 3
file2.txt 2

I want the achieve the following:

file1.txt
file2.txt
file1(1).txt
file1(2).txt
file1(3).txt
file2(1).txt

This is the code I have so far:

@echo off
set Source=C:\Users\siddique.gaffar\Desktop\Artworks
set Target=C:\Users\siddique.gaffar\Desktop\Artworks Copy
set FileList=C:\Users\siddique.gaffar\Desktop\Artwork TXT File\Book1.txt
echo.

if not exist "%Source%" echo Source folder "%Source%" not found & goto Exit
if not exist "%FileList%" echo File list "%FileList%" not found & goto Exit
if not exist "%Target%" md "%Target%"

for /F "delims=" %%a in ('type "%FileList%"') do copy "%Source%\%%a" "%Target%"


:Exit
echo.
echo press the Space Bar to close this window.
pause > nul
sid
  • 3
  • 7
  • 1
    The question is ambigous. Shall the batch avoid overwriting already present files in the target or shall it duplicate the source file if double mentioned in the Filelist? –  Jan 28 '17 at 20:36
  • 1
    What if there is already a file `file1(1).txt` in the target also? – aschipfl Jan 28 '17 at 22:20
  • Related: [Make a Batch File That Keeps Both Files When a Name Conflict Occurs](http://stackoverflow.com/q/14033582) – aschipfl Jan 30 '17 at 16:18

2 Answers2

0
@echo off
set "Source=C:\Users\siddique.gaffar\Desktop\Artworks"
set "Target=C:\Users\siddique.gaffar\Desktop\Artworks Copy"
set "FileList=C:\Users\siddique.gaffar\Desktop\Artwork TXT File\Book1.txt"
setlocal EnableDelayedExpansion
for /f "delims=" %%a in ('type "%FileList%"') do (
if not defined count set "count=1"
cd "%Target%"
if exist %%a (
set "curfile=%%a"
set "curfile=!curfile:~0,-4!"
set "curfile=!curfile!(!count!).txt"
if exist !curfile! (
set /a "count=!count! + 1"
set "curfile=%%a"
set "curfile=!curfile:~0,-4"
set "curfile=!curfile!(!count!).txt"
)
cd "%Source%"
ren "%Source%\%%a" "!curfile!"
xcopy "%Source%\!curfile!" "%Target%"
ren "%source%\!curfile!" "%%a"
) else (
xcopy "%Source%\%%a" "%Target%"
)
)
pause

replace all your code by this code. put this batch file in the same directory wher your files to copy is. p. s.: for now it works only with .txt files.

HackR_360
  • 192
  • 2
  • 9
  • 1
    @sid, "it did not work" is not a quite precise error description, is it? – aschipfl Jan 28 '17 at 22:19
  • Sorry did not come up with any error, THE CMD opened and closed without copying anything, Maybe I did not put the code in correctly – sid Jan 28 '17 at 23:21
  • I really appreciate all you help, Did not work for me, did not copy any file I did the following 1. saved code to notepad 2. saved file as a .bat 3, click the file to run Results= no files copies, explore window opens and closes – sid Jan 29 '17 at 01:05
  • Hi Put the .bat file in the source were the file to be copied are, nothing is been copied, just get a pop up window which opens and closes – sid Jan 29 '17 at 01:24
  • Sorry the same problem, No files are been copied and it opening and closing a window – sid Jan 29 '17 at 01:33
  • Sorry same error, Have doubled checked the paths and all is correct just to make sure have copied and pasted the paths here SOURCE C:\Users\siddique.gaffar\Desktop\Artworks TARGET=C:\Users\siddique.gaffar\Desktop\Artworks Copy FILELIST=C:\Users\siddique.gaffar\Desktop\Artwork TXT File\Book1.txt – sid Jan 29 '17 at 01:49
  • Thank you so much work perfect I will carry out a much larger test at work tomorrow I appreciate your help – sid Jan 29 '17 at 01:59
  • Sorry I have 1 more issue, If I have 4 file 1 it will only create it twice (file1.txt & file1(1).txt) can it work so that it copies the same file more than twice – sid Jan 29 '17 at 02:11
  • @HackR_360 the problem is the `goto`. `goto` inside a `for`-loop breaks the loop! Once it has executed the `goto` it will no longer go to the next iteration. – J.Baoby Jan 29 '17 at 08:19
  • Hi I got the following error C:\Users\siddique.gaffar\Desktop\Artworks\File1.JPG 1 File(s) copied C:\Users\siddique.gaffar\Desktop\Artworks\File2.jpg 1 File(s) copied C:\Users\siddique.gaffar\Desktop\Artworks\File1(1).txt 1 File(s) copied C:\Users\siddique.gaffar\Desktop\Artworks\File2(1).txt 1 File(s) copied The system cannot find the file specified. File not found - (2).txt 0 File(s) copied The system cannot find the file specified. File not found - %a 0 File(s) copied – sid Jan 29 '17 at 09:06
  • @sid It's because of the `goto`, it kind of destroys the `for` and its context including the loop variable. That's why it can't recognize it. In [this question](http://stackoverflow.com/questions/8481558/windows-batch-goto-within-if-block-behaves-very-strangely) it is explained why. In short, a `goto` tells the cmd interpreter: "stop what you were processing and go to the label". It will therefore abandon the `for` and forgot about its context. The same behaviour is encountered with `goto` and labels inside `if` blocks. Follow the link for a more detailed explanation. – J.Baoby Jan 29 '17 at 09:24
0

The following should do the trick:

@echo off 
set Source=C:\Users\siddique.gaffar\Desktop\Artworks
set Target=C:\Users\siddique.gaffar\Desktop\Artworks Copy
set FileList=C:\Users\siddique.gaffar\Desktop\Artwork TXT File\Book1.txt
echo.
if not exist "%Source%" echo Source folder "%Source%" not found & goto Exit 
if not exist "%FileList%" echo File list "%FileList%" not found & goto Exit
if not exist "%Target%" md "%Target%" 

for /F "usebackq tokens=1-2" %%a in ("%FileList%") do call :CopyFile "%%a" %%b


:Exit
echo.
echo press the Space Bar to close this window.
pause > nul
exit /b 0

:CopyFile
:: first argument  = filename
:: second argument = number of copies

REM A little trick that will put limit on 0 if second argument is empty or not a number
set secondarg=%~2
set /a limit=secondarg

REM if limit is invalid (not strict positive), exit the function
IF %limit% LEQ 0 (
    echo Invalid number of copies
    exit /b 1
)
IF NOT EXIST "%Target%\%~1" (
    copy "%Source%\%~1" "%Target%"
    IF %limit% LEQ 1 exit /b 0
    set /a limit-=1
)

REM File already exists: search correct index for filename
set index=0
set "targetfile=%target%\%~n1"
set file_ext=%~x1

:following
set /a index+=1
Rem if file with index %index% already exists, go back to get following index
IF exist "%targetfile%(%index%).%file_ext%" goto :following

Rem we have the correct index, now we can copy
set /a limit=index+limit-1
FOR /L %%g IN (%index%,1,%limit%) DO copy "%Source%\%~1" "%targetfile%(%%g).%file_ext%"
exit /b 0

Another option if you have long filenames is the use of usebackq and surrounding the path with double quotes in the for f loop instead of analyzing the output of the type command.

The function :CopyFile checks the existence of the file with an IF EXIST and uses a counter to find the next index for the filename of the new file. It uses path manipulation to construct a new filename with the index.

EDIT: I've added the possibility to read the number of copies needed from the textfile and specify that number as second argument to the :CopyFile function. If no number is given or the number is not strict positive (greater than 0), it won't make a copy.

PS: the "little trick" I used that will set %limit% to 0 in case the second argument is empty works because set with the /a flag will replace empty variables with 0. This won't work if you use argument variables directly though:

set /a limit=%~2

will throw an error if the second argument is empty because the cmd parser will substitute %~2 with an empty string and it will execute set /a limit= which is an invalid assignement using the /a flag. But if you use an extra variable as transit:

set var=%~2
set /a limit=var

you'll let set handle the variable expansion and not the cmd interpreter. The set will see that the var variable is empty (in the case %2 is empty) and will replace it with 0.

J.Baoby
  • 2,167
  • 2
  • 11
  • 17
  • Sorry to let you know I got the following error The system cannot find the file specified. The system cannot find the file specified. The system cannot find the file specified. The system cannot find the file specified. press the Space Bar to close this window. – sid Jan 29 '17 at 01:20
  • @sid I forgot to add the source directory in the copy. It should be ok now – J.Baoby Jan 29 '17 at 08:07
  • Great to hear that! My pleasure – J.Baoby Jan 29 '17 at 09:09
  • @sid can you mark it as solution to your problem if you're satisfied with the answer? – J.Baoby Jan 29 '17 at 10:56
  • HI Sorry to bother you, Have been so much help, I have just realised I have not assigned the number of copies wanted e/g in teh text file I have 1 colum with the file1.txt file2.txt file1.txt file2.txt and in the 2nd column number of copies to be made Either 1 or 2 or 3 Is it possible to adjust the script to allow number of copies to be made ? – sid Jan 30 '17 at 15:29
  • It depends. Can the filename contain spaces? – J.Baoby Jan 30 '17 at 19:37
  • Tge filename dose not contain spaces – sid Jan 31 '17 at 08:16
  • Yes it is possible in that case. I'll edit my answer. It would be better if you would edit your original post too though. This way everyone who reads the post will understand the changes in the answer. – J.Baoby Jan 31 '17 at 08:39
  • 1
    Works Perfect Thank you very much, – sid Jan 31 '17 at 10:43
  • Hi I have another project, want to know if you can help – sid Apr 13 '17 at 23:21
  • @sid Sure. In the following 24hrs I will be AFK though. But after that I'll be glad to help. What can I help you with? – J.Baoby Apr 14 '17 at 01:15
  • I need to achieve the following -- I have a folder with 5,000 images need a prompt (pop up) to be asked file name wanted and copy from one folder rename file and move copy to a new folder . Original file name Image1.jpg Image2.jpg Rename file Image1_1234.jpg Image2_1234.jpg The _1234 will always stay the same Any help would be much appreciated – sid Apr 14 '17 at 08:12
  • Hi Sorry wanted to make sure you got my last message – sid Apr 16 '17 at 19:40
  • You can create a batch-file and use `%n` to get the n-th argument passed to your script or [`set /p var=`](https://ss64.com/nt/set.html) to ask a user dor input. For the copying part I would recommend the [`copy`](https://ss64.com/nt/copy.html) command or the more robust [`robocopy`](https://ss64.com/nt/robocopy.html) – J.Baoby Apr 17 '17 at 03:25
  • @sid my apologies for the late answer. This part of the year is a bit busy :-( hope my comment helps. Feel free to ask for help if something is blocking you :-) – J.Baoby Apr 17 '17 at 03:27
  • Hi sorry I am stuck again, I would like the script to search Source sub-folders – sid Mar 09 '18 at 02:22
  • What do you mean with "search Source subfolders"? Maybe you can ask a new question? You'll have the possibility to expand and get helpful answers from other users as well :) – J.Baoby Mar 09 '18 at 09:12
  • Sorry I mean search for file in sub-directories of the source folder EG Source folder is C:\Users\siddique.gaffar\Desktop\Artworks Within this folder there are sub folders – sid Mar 09 '18 at 13:32
  • Does the target directory have to yield the same directory structure as the target? I.e. if the file is in a subdirectory in the source directory, will it have to be copied in the same subdirectory in the target directory? – J.Baoby Mar 09 '18 at 17:39
  • yes it is in a sub-directory in the source Source=C:\Users\siddique.gaffar\Desktop\Artworks file are in C:\Users\siddique.gaffar\Desktop\Artworks\LARGE And C:\Users\siddique.gaffar\Desktop\Artworks\SMALL etc. – sid Mar 09 '18 at 21:20
  • But do you want a SMALL and LARGE directory in your target directory as well? – J.Baoby Mar 10 '18 at 18:56
  • Sorry to bother you my new .txt file has also change to filename filename and number of copies – sid Mar 10 '18 at 19:12
  • small is in a sub directory and large is in another sub directory, and both and in the main directory – sid Mar 10 '18 at 19:14
  • Do you also want a those subdirectories to be created in the target directory? – J.Baoby Mar 11 '18 at 10:17
  • Sorry to bother you, I have worked out the issue and now all is working fine – sid Mar 16 '18 at 14:22
  • Great to hear you've been able to find the solution to your problem :) – J.Baoby Mar 16 '18 at 23:23