I need to toggle the names of two specific files existing at a specific path on the local drive and wonder if a .bat or a .vbs can achieve that.
In other words executing the script once swaps "File A" with "File B" ("C:\Path A\File A.txt" with "C:\Path A\File B.txt") and running it once more will swap them again.
I am also curious to know if the same can be done:
1) In this situation -->> "C:\Some Path\File A.txt" and "D:\Some Other Path\File B.txt"
and
2) If instead of two files I want to toggle two folders.
Create the following batch file and name it whatever you want. I'm using the name "myRename.bat".
:: myRename.bat
#echo off
SETLOCAL
:: verify the first file exists
if not exist "%~1" ( echo ERROR: File not found "%~1" & goto endofscript )
:: verify the second file exists
if not exist "%~2" ( echo ERROR: File not found "%~2" & goto endofscript )
:: Create a guaranteed unique string for temporarily naming one file
set instance=%date:~-4,4%%date:~-10,2%%date:~-7,2%
set instance=%instance%-%time:~0,2%%time:~3,2%%time:~6,2%%time:~9,2%
set instance=%instance%-%RANDOM%
:: rename the first file to a temporary name
ren "%~1" "%~nx1.%instance%"
:: rename the second file to the first file name
ren "%~2" "%~nx1"
:: rename teh first file to the second file name
ren "%~1.%instance%" "%~nx2"
:endofscript
Assuming these two files exist in this path:
c:\temp\Rename test\File A.txt
c:\temp\Rename test\File B.txt
Then you can run the command below and they will swap names:
myRename "c:\temp\Rename test\File A.txt" "c:\temp\Rename test\File B.txt"
If either File A or File B are not found, that error is reported on screen and the process stops.
Related
I'm trying to compare filenames from two folders and delete if duplicate found from ParentFolder.
I'll explain bit more as follows,
Files I'm trying to process through batch script
ParentFolder
300103666600005_20221215T075949_0090002504.xml
300103666600003_20221215T075948_00900025054.xml
300103666600003_20221215T075977_0090002506223.xml
300103666600004_20221215T095950_009000250702.xml
And then the content modified files will be copied to a child folder(TargetFolder1) by adding _signed suffix at the end of the file name as shown below,
300103666600005_20221215T075949_0090002504_signed.xml
300103666600003_20221215T075948_00900025054_signed.xml
300103666600003_20221215T075977_0090002506223_signed.xml
300103666600004_20221215T095950_009000250702_signed.xml
What I was trying to do...
First copy the XML files which are not exists in the child folders.
Get the file name from ParentFolder without extension & assume it to a variable called match1
Get the file name from child folder without extension by omitting _signed & assume it to a variable called match2
Check whether match1 = match2. If so, delete that matching file from Source folder only. (Which means we already processed & signed this file and we no longer need unprocessed file in the ParentFolder)
Following is the code I used to achieve this,
#echo off
setlocal EnableExtensions EnableDelayedExpansion
set "ParentFolder=D:\Test\QGenV1"
set "TargetFolder1=D:\Test\QGenV1\ESIGN"
set "TargetFolder2=D:\Test\QGenV1\ECOMP"
if not exist "%SourceFolder1%\" echo ERROR: Missing source folder 1: "%SourceFolder1%"& goto ErrorExit
if not exist "%TargetFolder%\" echo ERROR: Missing source folder 2: "%SourceFolder2%"& goto ErrorExit
md "%TargetFolder1%" 2>nul
md "%TargetFolder2%" 2>nul
if exist "%TargetFolder1%\" goto Process
if exist "%TargetFolder2%\" goto Process
echo ERROR: Failed to create target folder: "%TargetFolder1%"
echo ERROR: Failed to create target folder: "%TargetFolder2%"
:ErrorExit
echo/
pause
exit /B 1
:Process
rem Copy all files being unique in ParentFolder to TargetFolder1.
for %%I in ("%ParentFolder%\*.xml") do (
if not exist "%TargetFolder2%\%%~nxI" COPY "%%I" "%TargetFolder2%\"
if not exist "%TargetFolder1%\%%~nxI" COPY "%%I" "%TargetFolder1%\"
)
rem Delete existing files
for /f "tokens=*" %%l in ("%ParentFolder%\*.xml") do (
set filename=%%~nl
echo From Parent !match1!
for /f "tokens=*" %%A in ("%TargetFolder1%\*.xml") do (
set filename2=%%~nA
echo From Target !match2!
if "!match2!" == "!match1!" DEL /F "%ParentFolder%\!match1!.xml"
)
)
pause
endlocal
What Happened & what went wrong?
Copying only the XML file from Parent folder to Child folders
(TargetFolder1 & TargetFolder2) - Success
Extracting Filename without extension - Success
Extracting Filename without _signed suffix from TargetFolder1 -
Success
Comparing & deleting the file from ParentFolder - Partially
successful. And that is the problem.
What do I mean by 'Partial success is that the deleting process only works until the first occurrence of a file delete happens. Iterating through remaining files to compare & delete process doesn't continue if the second comparison is unmatched.
Any help would be great...
Windows 7/8/10 (x86/x64)
Window Batch
Hi all,
Firstly, the task I have been given:
A music library drive is backed up to a secondary drive every day using Robocopy.
Due to the possibility of deleting a file on the music library, the two cannot be mirror clones. Only different/new files are copied over to the backup drive.
Sometimes, it is discovered that a file(s) are in an incorrect folder on the music library and are moved to their correct folder. When the backup script is engaged, it then copies these 'new' files and their 'new' folder to the backup drive. The backup drive then has two copies of the file(s), one in it's correct 'new' position in the tree, and the other is the old erroneous one. The old is an unwanted duplicate.
I have so far managed to script the following:
Run through the latest Robocopy Log file (RClog), converting source file path to correct path on the backup drive. So it can be compared.
DIR the backup drive and dump to text file.
Put the converted RClog into an 'array' of variables.
Run through each line in the DIR list and compare the filename against the array. If it's a match, see if the full path matches. If not a fullpath match, then it's a possible* duplicate. Output full path to txt file.
So, I have my current code below.
It is painfully slow however. I think this is because I am performing close to 1 million actions! There are around 10k mp3 files, and about 100 newly copied files in the RClog.
I am thinking that I need to start, instead, with the smaller list of file, the RClog, and find those files in the DIR_List of the backup drive. However, I notice that FINDSTR doesn't like backlashes and needs them escaping. This would require a FOR loop to do variable substring substitution, which could slow things down some for both lists.
There is a final task I must perform, and that will be to MD5 hash the proposed unwanted duplicate file, and see if it's the same as the newly copied. *It could be that it happens to share the same name, but be from a different artist, so that needs to be checked. Some human intervention will likely be required at some point here, but for the most part automation is key, and quicker automation.
Whilst I really would prefer to keep this pure batch without 3rd party tools, I would consider using PowerShell as long as it's up to v3.0. I don't want to have to update things on the systems, and force changes. I am trying to work with what is there, and pure batch is available.
I apologise in advance for the rather casual commenting style.
Thanks in advance for any contributions.
::#ECHO OFF
#ECHO:
#ECHO: ===========================================================
#ECHO:
#ECHO: Music_library backup duplicate files finder
#ECHO:
#ECHO: Finds duplicate files to those included in the specified
#ECHO: robocopy log and lists them in a text file on the desktop
#ECHO:
#ECHO: ===========================================================
#ECHO:
:: Define Duplicates log
SET "DUPE_CHECK_LOG=%userprofile%\desktop\duplicates_log.txt"
:: Define Directory to scan
SET "IN_DIR=U:\Backups\Music_Library"
:: Define temporary DIR txt file
SET "TMP_DIR_TXT=%TMP%\Temp_Dir_list.txt"
:: FOR THE ROBOCCOPY LOG COPIED FILE PATH CONVERTER
:: Define Temporary robocopy log converted path file
SET "TMP_RC=%TMP%\Temp_RC_Conv.txt"
:: Define common root folder between both locations
:: copied from (in the Rc log) and backup location.
SET "CommonSplit=\Digital_Music_Library\"
:: END SECTION
:: Put rc log file path into a variable for easier reading
SET /P "RC_LOG=Drag and drop desired Robocopy Log here > "
:: strip rc log down to name.ext only
FOR /F "tokens=*" %%a IN ("%RC_LOG%") DO SET "RC_LOG_name=%%~nxa"
:: Print rc log name to new entry in dupes log
(
#ECHO:
#ECHO: %RC_LOG_name%
)>>"%DUPE_CHECK_LOG%"
:: Debug
::PAUSE
:: Delete old converted robocopy log if present
IF EXIST "%TMP_RC%" DEL /Q "%TMP_RC%"
:: Delete old dir txtif present
IF EXIST "%TMP_DIR_TXT%" DEL /Q "%TMP_DIR_TXT%"
:: Convert Robocopy Log to a list of those files in their new location
:: on the target drive. RC log lists 'from' location not 'to', so all
:: files wouldn't share the same path - different drive altogether.
:: Need to string path of copied files down to a common root folder
:: between the two locations. eg. Digital_Music_Library
FOR /F "tokens=3 delims= " %%a IN ('FINDSTR /C:"New File" "%RC_LOG%"') DO (
CALL :RC_CONVERTER "%%~fa"
)
:: Debug
::PAUSE
:: Take all of the data from text file and jam it into an array of variables
:: Each number of the var corresponds to that line in the text file...sheesh!
:: One var name for full path, the other for filenameext.
:: I just don't want yet another FOR loop to play with paramters/arguments - eg. %%~dpnxa
:: Shove this bit after the RC log is created, but really before anything else.
:: EnableDelayedExpansion must persist, can't ENDLOCAL on it yet, as it'll clear the var array!
SETLOCAL EnableDelayedExpansion
SET /A i=0
FOR /F "usebackq tokens=*" %%a IN ("%TMP_RC%") DO (
SET /A i+=1
SET "ArrayFullPath[!i!]=%%~fa"
SET "ArrayFilenameExt[!i!]=%%~nxa"
)
:: debug
::PAUSE
:: Dumps contents of music library into a txt file, all mp3s.
DIR /b/s "%IN_DIR%\*.mp3">>"%TMP_DIR_TXT%"
:: Loop through each line in Dir.txt checking if file is dupe
FOR /F "usebackq tokens=*" %%a IN ("%TMP_DIR_TXT%") DO (
CALL :CHECKER "%%~fa"
REM PAUSE
)
:: End out commands
:: Delete old converted robocopy log if present
IF EXIST "%TMP_RC%" DEL /Q "%TMP_RC%"
:: Delete old dir txtif present
IF EXIST "%TMP_DIR_TXT%" DEL /Q "%TMP_DIR_TXT%"
#ECHO:
#ECHO: Finished finding duplicates.
ENDLOCAL
PAUSE
GOTO :EOF
:CHECKER
:: Start at 1 and go to the maximum number of array vars created earlier.
:: For each one compare the found filename.ext from above against the filename.ext in the array
:: If it matches, make sure the path doesn't, and then print full path to duplicate file to a text file.
:: End subroutine and go back for the next found file.
FOR /L %%a IN (1,1,%i%) DO (
IF /I "!ArrayFilenameExt[%%a]!" == "%~nx1" (
IF /I NOT "!ArrayFullPath[%%a]!" == "%~f1" (
FOR /F "tokens=*" %%z IN ("%~f1") DO (
ECHO %%~fz>>"%DUPE_CHECK_LOG%"
)
)
)
)
EXIT /B
:RC_CONVERTER
:: Take the full path from the RC log sent as paramter/argument
:: Use variable substring substitution to remove everything before and
:: including the common folder.
:: Print out to text file target drive, path, common folder and remaining path of
:: copied files.
SET "TMP_STR=%~f1"
CALL SET "TempStr=%%TMP_STR:*%CommonSplit%=%%"
FOR /F "tokens=*" %%g in ("%TempStr%") DO (
#ECHO %IN_DIR%%CommonSplit%%%~g>>"%TMP_RC%"
)
EXIT /B
Firstly I would like to say that it has been 10 years since I dabbled in programming and my memory of what I have learnt seems to be failing me. I hope I have included enough info for people to see what I am trying to do without going to extremes. There may be better ways to do what I have done and any suggestions will be appreciated.
I have 2 batch files, both in the parent directory, 1 to back up files in 2 sub directories of the parent directory to another sub directory a few levels down from the parent directory.
eg.
The batch files are in the directory "Test Folder"
The files to be backed up are in the location :-
Test Folder\LocalProfiles
and
Test Folder\SavedLocal
The folder where they are to be backed up to is called "Backup" with created directories using a name chosen by the users eg. "Blue" and then in another directory under that using the current Date and Time as the name of the directory, followed by the original directory. (The format of the date and time, currently 2016-04-06 23.03.15 has not been finalised as the space that I am using in the backup batch file between the date and time has been giving me problems in this batch file when restoring). So the location of the files for this user that have been backed up would be:-
Test Folder\Backup\Blue\2016-04-06 23.03.15\LocalProfiles
and
Test Folder\Backup\Blue\2016-04-06 23.03.15\SavedLocal
I have written a batch file that lists all of the user chosen directories
1st Screen
then after the user chooses a directory they then choose a directory from the directories labeled with a date and time
2nd Screen
and then it copies the files below back to the original location.
The problem with this is that it takes time and can lead to typos, especially when putting in the date and time. I wanted to make it as fool proof as possible by creating a menu where the user can select a number corresponding with a user created directory.
The end result would be:-
1st menu screen
Select one of the following
1. Blue
2. Red
3. Green
etc.
and then display the directories with dates and times that are contained in the selected directory on the next menu screen.
2nd Menu
Select one of the following
1. 2016-04-05 21.03.28
2. 2016-04-05 21.05.51
3. 2016-04-06 23.00.14
etc.
The user would simply type the number corresponding to the selected directory and press enter.
In the end I would like to merge both batch files with a choice to backup or restore but I need this to work properly first.
The following is the code for restoring the files, without the use of menus. It works but it doesn't always handle spaces in directory names and I'm sure there would be a better way to handle the error checking and messages.
#echo off
if not defined in_subprocess (cmd /k set in_subprocess=y ^& %0 %*) & exit )
:Prompt for Profile Name
cls
echo.
echo Please select one of the following Profiles to load.
echo.
:: Create the list of Profiles from the Directory Names
for /d %%D in (.\Backup\*) do echo %%~nxD
echo.
:: Prompt for Profile Name for multiple Profile Names
set "profile="
set /p profile=Please enter a Profile Name.
:: OR
:: Consider adding Fixed Profile Name to top of list/menu as the default for quick saving of files.
:: set "profile=Default"
:: Check that the Profile exists
echo.
if not exist ".\Backup\%profile%" echo The Profile %profile% does not exist.
if not exist ".\Backup\%profile%" pause
if [%profile%] == [] echo A Profile must have a name.
if [%profile%] == [] pause
:: If input is empty or doesn't exist return to the beginning.
if not exist ".\Backup\%profile%" goto Prompt for Profile Name
if [%profile%] == [] goto Prompt for Profile Name
:Saved
:: Create the list of Saved locations from the Directory Names
cls
echo.
echo Existing Saved Locations for the Profile named %profile%
echo.
for /d %%S in (".\Backup\%profile%\*") do echo %%~nxS
:: Prompt for Saved location for selected Profile Name
set "save="
echo.
set /p save=Please enter a Saved location.
:: Check that the Saved Location exists
echo.
if not exist ".\Backup\%profile%\%save%" echo The Saved Location %profile%\"%save%" does not exist.
if not exist ".\Backup\%profile%\%save%" echo Select a Saved Location from the list.
if not exist ".\Backup\%profile%\%save%" pause
:: Check that the Saved Location is not empty
if [%save%] == [] echo Select a Saved Location from the list.
if [%save%] == [] pause
:: If input is empty or doesn't exist return to the beginning.
if not exist ".\Backup\%profile%\%save%" goto Saved
if [%save%] == [] goto Saved
:: Check for Saved files
if not exist ".\Backup\%profile%\%save%\LocalProfiles\LocalData.profile" echo.
if not exist ".\Backup\%profile%\%save%\LocalProfiles\LocalData.profile" echo LocalData.profile for %profile% does not exist at location "%save%\LocalProfiles\"
if not exist ".\Backup\%profile%\%save%\SavedLocal\LocalMember.profile" echo.
if not exist ".\Backup\%profile%\%save%\SavedLocal\LocalMember.profile" echo LocalMember.profile for %profile% does not exist at "%save%\SavedLocal\"
:: If LocalData.profile doesn't exist display message and return to Saves.
if not exist ".\Backup\%profile%\%save%\LocalProfiles\LocalData.profile" echo.
if not exist ".\Backup\%profile%\%save%\LocalProfiles\LocalData.profile" echo The Save at %save% is incomplete or does not exist.
if not exist ".\Backup\%profile%\%save%\LocalProfiles\LocalData.profile" echo.
if not exist ".\Backup\%profile%\%save%\LocalProfiles\LocalData.profile" echo Please select another Save.
if not exist ".\Backup\%profile%\%save%\LocalProfiles\LocalData.profile" Pause
if not exist ".\Backup\%profile%\%save%\LocalProfiles\LocalData.profile" goto Saved
:: If LocalMember.profile doesn't exist display message and return to Saves.
if not exist ".\Backup\%profile%\%save%\SavedLocal\LocalMember.profile" echo.
if not exist ".\Backup\%profile%\%save%\SavedLocal\LocalMember.profile" echo The Save at %save% is incomplete or does not exist.
if not exist ".\Backup\%profile%\%save%\SavedLocal\LocalMember.profile" echo.
if not exist ".\Backup\%profile%\%save%\SavedLocal\LocalMember.profile" echo Please select another Save.
if not exist ".\Backup\%profile%\%save%\SavedLocal\LocalMember.profile" Pause
if not exist ".\Backup\%profile%\%save%\SavedLocal\LocalMember.profile" goto Saved
:Load Save
:: Restore the valid Save to the original location.
echo.
echo Restoring Saved Files
robocopy ".\Backup\%profile%\%Save%\LocalProfiles" ".\LocalProfiles"
robocopy ".\Backup\%profile%\%Save%\SavedLocal" ".\SavedLocal"
echo.
echo Files Restored
pause
exit
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "directories=localprofiles savedlocal"
CALL :zap$
:: First menu
CALL :choose blue default green red "white and puce stripes" /now
SET "userchosenname=%$choice%"
:: Don't know what format you are using for date and time.
:: I use dd/mm/yyyy and hh:mm:ss.hh
SET "backupdatestamp=%date:~-4%-%date:~3,2%-%date:~0,2% %time::=.%"
SET "backupdatestamp=%backupdatestamp:~0,-3%"
CALL :choose "backup as %backupdatestamp%"
FOR /f "delims=" %%a IN ('dir /b /ad "%sourcedir%\%userchosenname%\" 2^>nul') DO (
IF EXIST "%sourcedir%\%userchosenname%\%%a\localprofiles\." CALL :choose "restore from %%a"
)
CALL :choose /now "With this prompt"
FOR %%a IN (%directories%) DO (
IF "%$choice:~0,6%"=="backup" (
ECHO(MD "%sourcedir%\%userchosenname%\%backupdatestamp%\%%a"
ECHO(XCOPY /s/e "%sourcedir%\%%a" "%sourcedir%\%userchosenname%\%backupdatestamp%\%%a\"
) ELSE (
ECHO(XCOPY /s/e "%sourcedir%\%userchosenname%\%$choice:~13%\%%a\*" "%sourcedir%\%%a\"
)
)
GOTO :EOF
:: remove variables starting $
:ZAP$
FOR /F "delims==" %%Z In ('set $ 2^>Nul') DO SET "%%Z="
GOTO :EOF
:: Make a choice
:: If a parameter is '/now' actually make a choice with prompt next-parameter
:: else accumulate choices
:choose
SET "$item=%~1"
IF NOT DEFINED $item GOTO :EOF
IF /i "%$item%"=="/now" GOTO makechoice
IF NOT DEFINED $options cls
IF NOT DEFINED $choices SET "$choices=123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
SET "$options=%$options%%$choices:~0,1%"
SET "$choices=%$choices:~1%"
SET /a $optioncount+=1
SET "$option%$optioncount%=%~1"
ECHO(%$options:~-1% %~1
SHIFT
GOTO choose
:makechoice
IF "%~2" neq "" SET "$options=%$options% /m "%~2""
choice /c %$options%
CALL SET "$choice=%%$option%errorlevel%%%"
CALL :zap$&SET "$choice=%$choice%"
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances.
The required MD commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(MD to MD to actually create the directories. Append 2>nul to suppress error messages (eg. when the directory already exists)
The required XCOPY commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(XCOPY to XCOPY to actually copy the files. Append >nul to suppress report messages (eg. 1 file copied)
The basis of this routine is the :choose subroutine which accumulates options into $-variables. It can be run either with 1 or more parameters, optionally quoted (in case a parameter includes a space.)
If the parameter /now is found, the routine asks for a choice to be made from the options presented. If the /now parameter is followed by another, that following parameter is used as a prompt for choice.
The CALL :zap$&SET "$choice=%$choice%" line uses the same parsing trick used to export values from a setlocal/endlocal bracket
Beyond that, all you'd need to do is fix the setting of backupdatestamp using the batch substringing facilities explained in the documentation
set /?
from the prompt.
I want to accomplish the following: copy File A from Directory A to Directory B but File A already exist in Directory B and i don't want to overwrite it, simply put the new file in Directory B with a (1) or something so i'll know the difference. i can't manually name the file in the script as i plan to make it a batch file and run it every few hours therefore resulting in the same file existing with different names. IE. File A, File A(1), File A(2) so on and so on. please help. Thank you
Use Xcopy command with parameter /D
C:\> xcopy D:\source_dest E:\target_dest /E /D
/E parameter make that it copy files with subfolders
/D parameter make that it copy files without overwrite
if want more help inform me .if it works vote up
A cyclic copy refers to the situation where the source directory
contains the destination directory. Since the destination directory
is part of the source, the copying process eventually starts copying
the destination directory to a deeper portion of the destination.
This process will continue until, of course, the finite disk space
eventually runs out.
To avoid this condition but to achieve the objective, one can
specify a temporary destination which is on another volume (e.g.,
D:\temp\) and later copy the temporary destination to the final
destination, and delete the temporary directory at the end.
just check file exist before run xcopy command then run copy command
if NOT EXIST c:\directory B\File A ( xcopy c:\Directory A\File A c:\Directory B )
The following is made for folders but you can modify it for files.
Makes a backup of existed folder directory (and all contents in it) with new increase number in folder name [like TEST(1)... TEST(2)... folder].
The first part :Start will set the %PathFolder% variable with path to folder name (%userprofile%\Desktop\TEST) and then will search if exist. If NOT exists, will create it (xcopy), else, If exist, will directing the %PathFolder% variable to :Search label (for-)loop section for further handling...
Tip: Can be used %1 variable to set PathFolder set "PathFolder=%1" so it will work when you Drag-n-Drop a folder on this current saved batch file.
The second part :Search will search in the %PathFolder% variable (%userprofile%\Desktop\TEST) and will make a COPY of "TEST" folder (and all contents in it) with an increase number added in parenthesis at the end of folder name [like TEST(1)]. If already exist TEST(1) then will copy TEST folder as TEST(2) ... or TEST(3) ... and so on.
::Make a backup of existed folder directory (and all contents in it) with new increase number in folder name.
#echo off
setlocal EnableDelayedExpansion
set "IncrNum=1"
:Start
::The following will set the "%PathFolder%" variable with path to folder name (%userprofile%\Desktop\TEST) and then will search if exist. If NOT exists, will create it (xcopy), else, If exist, will directing the "%PathFolder%" variable to :Search label (for-)loop section for further handling...
::Tip: Can be used %1 instead of %userprofile%\Desktop\TEST in [set "PathFolder=..."] line so it will work when you Drag-n-Drop a folder on this current saved batch file.
set "PathFolder=%userprofile%\Desktop\TEST"
if NOT exist "%PathFolder%" (
xcopy %PathFolder% %PathFolder% /i /y
exit /b
) else (
goto :Search
)
exit /b
:Search
::The following will search in the "%PathFolder%" variable (%userprofile%\Desktop\TEST) and will make a COPY of "TEST" folder (and all contents in it) with an increase number added in parenthesis at the end of folder name [like TEST(1)]. If alredy exist TEST(1) then will copy TEST folder as TEST(2) ... or TEST(3) ... and so on.
for /f "tokens=*" %%G in ('dir /b /s /a:d "%PathFolder%*"') do (
if exist %%G^(%IncrNum%^) (
echo At "%%~dpG" a folder "%%~nG(%IncrNum%)" alredy existed.
set /a IncrNum+=1
goto :Search
) else (
echo.
echo.
echo The "%%~nG" folder and all contents in it
echo will be copied now as "%%G(%IncrNum%)".
echo.
pause
xcopy %%G %%G^(%IncrNum%^) /i /y
exit /b
)
)
:EndBatch
set "PathFolder="
pause
exit
I want to parse a directory and its subdirectories and copy all files in a target directory ignoring the original folder structure. All files shall be copied directly in the target directory.
I found a nice solution here for the Windows command line:
for /r FolderA %f in (*) do #copy "%f" target
https://stackoverflow.com/a/1502183/772434
That in general works fine, but I have duplicate files in the source directory which have the same name. There are too many files, so I can not handle those exceptions by hand.
How can I handle those files in the script automatically?
Options:
overwrite files during copying
keep copies and rename file e. g. by adding "__123" a number at the end of the file name
compare files (MDS5 sum or similar) and create copy only if files are different.
I would prefer option 3 (compare file content and keep numbered copies only if files are really different), but I'm also interested in solutions for options 1 and 2 (more pragmatic).
Here's an approach. i haven't tested it, so i hope it works as expected.
There is a global variable called CURRENT_DUPLICATE_SUFFIX. every time a file with the same name is found, but with different content, this value gets incremented and appended to the resulting file name
#echo off
SET SOURCE_DIR=C:\temp\LogAnalyzer
SET TARGET_DIR=C:\temp\test\output
SET CURRENT_DUPLICATE_SUFFIX=1
for /r "%SOURCE_DIR%" %%f in (*) do CALL :SUB1 "%%f"
GOTO END
:SUB1
SET PURE_FILE_NAME=%~nx1
SET TARGET_FILE_NAME=%TARGET_DIR%\%PURE_FILE_NAME%
IF NOT EXIST "%TARGET_FILE_NAME%" (
COPY %1 "%TARGET_DIR%"
GOTO :EOF
)
REM if we are here, the target file exists.
echo n |comp %1 "%TARGET_FILE_NAME%" >NUL 2>NUL
REM in case the files have the same content
IF %ERRORLEVEL%==0 GOTO :EOF
SET TARGET_FILE_NAME=%TARGET_FILE_NAME%_%CURRENT_DUPLICATE_SUFFIX%
SET /A CURRENT_DUPLICATE_SUFFIX=%CURRENT_DUPLICATE_SUFFIX%+1
COPY %1 "%TARGET_FILE_NAME%
GOTO :EOF
:END