in the bat file I got a simply command like :
xcopy "C:\Users\me\Documents\ApplyPatchBat" "C:\Users\me\Desktop\Test\" /S/E/K
This does the job where it will copy all the files including files inside subfolders. I know you can add /y to make it auto overwrite.
How ever I want to create an statement if this file that we are copying exist in the destination folder, copy the one in destination folder to a backup folder.
I wonder there is any IF statement I can add to after the command to detect if the file is existing? Or maybe an error level check when its asking do I want to overwrite? P.S. This is for applying new patches to a program, where there are many layers of folders, that's why I use the /S/E/K in xcopy.
xcopy itself can't backup beforehand, but with output from xcopy and a bit of for loop magic you can make this happen
#echo off
setlocal ENABLEDELAYEDEXPANSION
set source="C:\Users\me\Documents\ApplyPatchBat"
set target="C:\Users\me\Desktop\Test\"
rem /l = list only, /u = already existing, /y = yes to replace
rem /f = display full source and destination file names, /c = continue on errors
rem /s = subdirectories, /k = keep attributes
rem split the strings at ->, we're only interested in the part after ->
for /f "usebackq tokens=1,* delims=>" %%a in (`xcopy %source% %target% /l /u /y /f /c /s /k`) do (
set file=%%b
rem ignore lines without a destination, e.g. 15 file(s) copied
if x!file! neq x (
rem remove the leading space, original string is source -> destination
set file=!file:~1!
for %%f in ("!file!") do (
if not exist %%~dpf\backup\* md %%~dpf\backup
rem only backup if not already backed up
if not exist %%~dpf\backup\%%~nxf move %%f %%~dpf\backup
)
)
)
xcopy %source% %target% /y /c /q /s /k
Related
I want to make a batch file who is doing the following things, search all file of a type from all my computer, but exclude some directories from searching, like Windows or Program Files and copy only files în one folder, without the parent/parents directory/directories.
I tried in 3 ways:
First with ROBOCOPY command
ROBOCOPY C:\ %location% *.jpg *.png /S /XD "Windows" "Program Files" /XJ /W:0 / R:0
It's working perfect but i don't need the parents directory of the files, i want all files who was find to copy în one folder.
Second way was with XCOPY
XCOPY /C /H /S /EXCLUDE: excludefiles.txt "%source%" "%destination%"
But the same problem, copy files with their parents directories.
And third way with For Loop, where i used same xcopy.
FOR "eol=| delims=" %%f IN (*.jpg,*.png) DO ( XCOPY /C /H /S /EXCLUDE:excludefiles.txt "%source%\%%~nxf" "%destination%"
But same problem, i tried in for loop and with copy, but copy doesn't have options to search in subdirectories, what for me it's also a problem.
So if you can help me with this problem I will thank you.
I messed around a bit and came up with the following script (see all the explanatory rem remarks):
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "SOURCE=D:\" & rem // (root directory of source location)
set "TARGET=H:\copydata\" & rem // (target location)
set PATTERNS="*.jpg","*.png" & rem // (list of file patterns)
set EXCLUSIONS="D:\dontcopy\","\ignoreit\" & rem // (list of exclusions)
set "EXCLFILE=exclusions.lst" & rem /* (name of temporary exclusions file;
rem this must not contain spaces!) */
set "EXCLFDIR=%~dp0" & rem /* (location of temporary exclusions file;
rem `%~dp0` is the parent dir. of this script) */
rem // Create temporary exclusions file:
cd /D "%EXCLFDIR%"
if defined EXCLUSIONS (
> "%EXCLFILE%" (
for %%E in (%EXCLUSIONS%) do (
echo(%%~E
)
)
rem // Build exclusions option for `xcopy`:
set "EXCLUSIONS=/EXCLUDE:%EXCLFILE%"
)
rem /* Create target directory to ensure it exists
rem (if the target does not exist, `xcopy` prompts for
rem whether it is a File or a Directory; if it exists,
rem no prompt appears; `2> nul` surpresses error message
rem of `md` in case the target already exists): */
2> nul md "%TARGET%"
rem // Enumerate all files in source recursively:
for /F "eol=| delims=" %%F in ('
cd /D "%SOURCE%" ^& dir /B /S /A:-D %PATTERNS%
') do (
rem // Do the actual flat copying here:
(
rem /* Surpress output (also `1 File(s)`) by `> nul`
rem (`xcopy` outputs the copied file plus the summary
rem `1 File(s)`; to avoid that summary after each file,
rem the entire output of `xcopy` is surpressed): */
> nul xcopy /L /Y /C /H /K %EXCLUSIONS% "%%~F" "%TARGET%"
rem /* (after testing, remove `/L` to do actual copying) */
) && (
rem /* Return every copied file to see what has been copied;
rem `&&` lets `echo` execute inly if `xcopy` succeeded: */
echo(%%~F
)
)
rem // Delete temporary exclusions file:
del "%EXCLFILE%"
endlocal
exit /B
You do not need to create an exclusions file for xcopy (as in your similar previous question), because that file is created automatically by the script, temporarily. You simply need to define all the file and directory locations, file patterns and exclusions in the section with the Define constants here: remark.
After having tested whether the output lists all files you want to copy, you need to remove the /L switch from the xcopy command in order to actually copy and files.
I'd use the last command with a minor change:
FOR /F "delims=" %%f IN ('dir /s/b *.jpg,*.png') DO ( XCOPY /H /S "%%~f" "%destination%")
This will loop over all files listed by dir /s/b *.jpg,*.png there are additional attributes for hidden / system files etc.
Then it simply copies everything into the flat destination folder. Note: the destination folder must end in a \
----- edit - repeating for another partition ------
set destination=c:\temp\batches\dir3\
FOR /F "delims=" %%f IN ('dir /s/b c:\*.jpg') DO call :copyWithExcludes %%f
FOR /F "delims=" %%f IN ('dir /s/b d:\*.png') DO call :copyWithExcludes %%f
pause
goto:eof
:copyWithExcludes
XCOPY /H /S /Y "%~1" "%destination%"
goto:eof
I try to write a script that can monitor a folder H:\Start and copy a new subfolder with its files in H:\Start to new location H:\Target. The script should store the copied folder and files in a text file.
Each time the script starts new and monitors H:\Start, it should check the text file and copy only those subfolders which are not yet included in the text file because copied already before.
I was searching the world wide web for examples, but could not really find a starting point. Any help would be nice.
I have so far not working good :)
#echo off
setlocal EnableDelayedExpansion
pushd %1
for /D %%d in (“H:\Start\*.*”) do set n=!n!;%%d
if defined n echo %n:~1% > C:\Desktop\list.txt
popd
endlocal
for /f %%i in (C:\Desktop\list.txt) do not (
xcopy /d /s H:\Start H:\Target > C:\Desktop\list.txt >nul 2>&1
)
I suggest using:
%SystemRoot%\System32\xcopy.exe H:\Start H:\Target /C /H /I /K /M /Q /R /S /Y >nul
For information about all those parameters of xcopy open a command prompt window and run there xcopy /? to get help of this command displayed which explains all those parameters.
The important one is /M which selects for copying process just files with archive attribute set and which removes the archive attribute on each file in H:\Start after copying the file. This avoids that a once copied file is copied once more as long as not modified in H:\Start since last copy.
If you want to log all copied files into a text file, I suggest using:
%SystemRoot%\System32\xcopy.exe H:\Start H:\Target /C /F /H /I /K /M /R /S /Y >>C:\Desktop\list.txt
The names of the copied files are with this command line appended to text file C:\Desktop\list.txt
The following commented batch code works with directory lists as asked for.
#echo off
rem Define source and destination directory as well as
rem the names of the used list files each with full path.
setlocal EnableExtensions
set "Source=H:\Start"
set "Destination=H:\Target"
set "MainDirList=C:\Desktop\list.txt"
set "CurrentList=%Temp%\CurrentList.tmp"
set "ExcludeList=%Temp%\ExcludeList.tmp"
set "FinalDoList=%Temp%\FinalDoList.tmp"
rem Write the names of all subdirectories found in source
rem directory into a list file in directory for temporary files.
dir /AD /B "%Source%">"%CurrentList%"
rem Check if list file is not empty because of no subdirectories.
call :CheckEmpty "%CurrentList%"
if %FileIsEmpty% == 1 (
echo No directories in %Source%
goto EndBatch
)
rem Start copying the directories if there is no main list file
rem from a previous execution of this batch file or the main list
rem file was deleted intentionally to force copying all again.
if not exist "%MainDirList%" goto CopyDirectories
rem Start copying also if main list file is an empty file.
call :CheckEmpty "%MainDirList%"
if %FileIsEmpty% == 1 del "%MainDirList%" & goto CopyDirectories
rem Search in main list for lines matching completely lines in current
rem list with ignoring case and write the found lines into an exclude
rem list file as those directories were copied already before.
%SystemRoot%\System32\findstr.exe /I /L /X /G:"%CurrentList%" "%MainDirList%" >"%ExcludeList%"
rem Copy all directories if no line in current list is found in main list.
if errorlevel 1 goto CopyDirectories
rem Get all lines from current list not listed also in exclude list.
%SystemRoot%\System32\findstr.exe /B /I /L /V /G:"%ExcludeList%" "%CurrentList%" >"%FinalDoList%"
rem Replace the current list with the reduced final list.
move /Y "%FinalDoList%" "%CurrentList%"
rem Check if remaining current list is not empty because
rem all subdirectories copied already before.
call :CheckEmpty "%CurrentList%"
if %FileIsEmpty% == 1 (
echo Copied already before all directories in %Source%
goto EndBatch
)
:CopyDirectories
rem Copy each directory in remaining current list file.
for /F "usebackq delims=" %%D in ("%CurrentList%") do (
echo Coping %Source%\%%D
%SystemRoot%\System32\xcopy.exe "%Source%\%%D" "%Destination%\%%D" /C /H /I /K /Q /R /S /Y >nul
)
rem Append the list of copied directories to main list file.
type "%CurrentList%">>"%MainDirList%"
goto EndBatch
:CheckEmpty
rem This little subroutine just checks if size of a list file is 0.
if %~z1 == 0 ( set "FileIsEmpty=1" ) else ( set "FileIsEmpty=0" )
goto:EOF
:EndBatch
rem Delete all not further needed listed files and environment variables.
del "%ExcludeList%" 2>nul
del "%CurrentList%"
endlocal
This batch file should work for the FTP folder mounted as drive on Windows. It does not depend on attributes or timestamps. It uses explicitly only the names of the directories in H:\Start. It also does not check which directories exist already in H:\Target. Therefore it is possible to delete a directory in H:\Target if not interested in and the deleted directory will be nevertheless not copied once again from H:\Start as long as the deleted directory is not also removed from main list file.
For details on parameters used on findstr run in a command prompt window findstr /? and read the entire help output into the window.
Thanks for this question as this was really an interesting batch coding task.
You don't need to store anything, you can use
xcopy /d /s h:\start h:\target
/D:mm-dd-yyyy
Copy files changed on or after the specified date.
If no date is given, copy only files whose
source date/time is newer than the destination time.
but if you need a list of the files you can just use a redirection :
xcopy /d /s h:\start h:\target > logfile.txt
I want to write a batch file that creates a folder (if it does not exist) and copies a certain file into that folder. So far so good.
The problem is that one folder in the path varies slightly from time to time, so a wildcard becomes necessary.
The following code works just fine but obviously misses to create the folder (Reports). So if the folder is not there, it simply does nothing.
for /r "c:\Users\%USERNAME%\AppData\Local\Packages" &&G in ("LocalState\acn\Reports") do #if exist %%G xcopy /s /i /y c:\temp\Reporting "%%G"
The full path is:
c:\Users\FSchneider\AppData\Local\Packages\“WILDCARD"\LocalState\acn\Reports\
Any idea?
Add /d switch in for to indicate you're looking for a directory, not a file
Add * and omit quotes in the wildcard to indicate it's actually a wildcard
No need for if exist now
for /d /r "%LocalAppData%\Packages" %%G in (LocalState\acn.*) do xcopy /s /i /y c:\temp\Reporting "%%G\Reports"
Next script could help.
#ECHO OFF
SETLOCAL enableextensions
set "_fldrtop=%USERPROFILE%\AppData\Local\Packages"
set "_fldrsub=LocalState\acn"
if not "%~1"=="" set "_fldrsub=%~1" :: my testing data, remove this line
set "_fldrlow=Reports"
if not "%~2"=="" set "_fldrlow=%~2" :: my testing data, remove this line
for /F "delims=" %%G in ('dir /B /AD "%_fldrtop%"') do (
if exist "%_fldrtop%\%%G\%_fldrsub%\" (
if exist "%_fldrtop%\%%G\%_fldrsub%\%_fldrlow%\" (
echo echo "%_fldrtop%\%%G\%_fldrsub%\%_fldrlow%\"
) else (
echo md "%_fldrtop%\%%G\%_fldrsub%\%_fldrlow%\"
)
rem echo xcopy /s /i /y c:\temp\Reporting "%_fldrtop%\%%G\%_fldrsub%\%_fldrlow%\"
)
)
Output:
==>D:\bat\SO\31672436.bat
==>D:\bat\SO\31672436.bat "LocalState\Cache"
md "C:\Users\UName\AppData\Local\Packages\winstore_cw5\LocalState\Cache\Reports\"
==>D:\bat\SO\31672436.bat "LocalState\Cache" 2
echo "C:\Users\UName\AppData\Local\Packages\winstore_cw5\LocalState\Cache\2\"
I want to create a batch file to compare two folders with the same set of files and copy any files that are different in size from one folder to the other. I tried to adapt the answer from another question as follows as a starting point, but even this doesn't work.
#echo off
Set folder1="C:\folder1"
Set folder2="C:\folder2"
Cd /D "%folder1%"
For %%a in (*.*) do (
For %%b in ("%folder2%\%%a") do (
If "%%~Za" neq "%%~Zb" echo Different file size in %%a
)
)
Update1:
I figured out what was wrong in the example above; it was the quotes around the directories in the set folder commands. The following works as it should:
#echo off
Set folder1=C:\folder1
Set folder2=C:\folder2
Cd /D "%folder1%"
For %%a in (*.*) do (
For %%b in ("%folder2%\%%a") do (
If %%~za neq %%~zb echo Different file size %%a
)
)
Update2:
So this finally does what I want (compares two folders with the same set of files and copies any files that are different in size from one folder to the other):
#echo off
Set folder1=C:\folder1
Set folder2=C:\folder2
Cd /D "%folder1%"
For %%a in (*.*) do (
For %%b in ("%folder2%\%%a") do (
If %%~za neq %%~zb xcopy "%folder1%\%%a" "%folder2%" /y
)
)
The classic way to do this is
xcopy /L /y /d "directory1\*" "directory2"
The /L LISTS the files that would be copied. /d actually says "if the source file in the first parameter is later than the file in the second" which may not be what you want. The /y prevents a prompt for ovewrite (with the /L switch, just a listing is created, but still...)
Files existing in the source but not in the destination will be copied to the destination (or listed if the /L switch is used)
Remove the /L switch to actually perform the copy.
Add /s to repeat for all subdirectories of the source.
I have a text file containing a list of files and folders. What I want to do is use xcopy to replicate what is written in the text file. My text file looks like this:
"C:\FOLDER"
"C:\FOLDER\FILE1.TXT"
"C:\FOLDER\FILE2.TXT"
"C:\FOLDER\FOLDER2"
"C:\FOLDER\FOLDER2\FILE3.TXT"
For a given output directory "C:\OUTPUT" I would like to replicate the entire structure, so:
"C:\OUTPUT\FOLDER"
"C:\OUTPUT\FOLDER\FILE1.TXT"
"C:\OUTPUT\FOLDER\FILE2.TXT"
"C:\OUTPUT\FOLDER\FOLDER2"
"C:\OUTPUT\FOLDER\FOLDER2\FILE3.TXT"
How can I accomplish this? So far I have written a for loop that reads in each line of the file, but it copies all files if the line is a folder. What I want to do is only copy and create the files and folders that are mentioned in the text file.
#echo off
for /f "delims=] tokens=1*" %%a in (textfile.txt) do (
XCOPY /S /E %%a "C:\OUTPUT"
)
Am I on the right track?
Thank you and best regards,
Andrew
Yes, you are close. Just need to use the existing path as the appended destination path.
Update
#echo off
for /f "delims=" %%A in (textfile.txt) do if exist "%%~fA\*" (
md "C:\Output\%%~pA"
copy /y "%%~fA" "C:\Output\%%~pnxA"
)
Original
If %%A = "C:\Folder\Folder2\File3.txt", then %%~pA = Folder\Folder2
#echo off
for /f "delims=" %%A in (textfile.txt) do (
md "C:\Output\%%~pA"
if not exist "%%~fA\*" echo f | xcopy "%%~fA" "C:\Output\%%~pnxA" /y
)
The if not exist "%%~fA\*" makes sure to only copy the entry if it is not a directory. See Reference for more Techniques and Comments
Type in for /? at the command line to view a list of the variable modifiers. %%~A will remove the surrounding quotations (if any) from the variable.
Post about xcopy prompting issue. and fix #2.
Alternate Setup, since you most likely will not need the xcopy abilities.
#echo off
for /f "delims=" %%A in (textfile.txt) do (
md "C:\Output\%%~pA"
if not exist "%%~fA\*" copy /y "%%~fA" "C:\Output\%%~pnxA"
)