Merge 2 .bats in only one - batch-file

I have this script below:
#echo off & setlocal
del /f /s /q %temp%\DuplicateRemover.txt
del /f /s /q %temp%\DuplicateRemover.bat
echo SetLocal DisableDelayedExpansion >>%temp%\DuplicateRemover.txt
echo #echo off ^& setlocal >>%temp%\DuplicateRemover.txt
echo rem Group all file names by size >>%temp%\DuplicateRemover.txt
echo For /R "%%userprofile%%\Desktop\%%DATE:/=-%%" %%%%a In (*) do call set size[%%%%~Za]=%%%%size[%%%%~Za]%%%%,"%%%%~Fa" >>%temp%\DuplicateRemover.txt
echo rem Process groups >>%temp%\DuplicateRemover.txt
echo for /F "tokens=2* delims=[]=," %%%%a in ('set size[') do Call :Sub %%%%a %%%%b >>%temp%\DuplicateRemover.txt
echo Goto ^:Eof >>%temp%\DuplicateRemover.txt
echo ^:Sub >>%temp%\DuplicateRemover.txt
echo If "%%~3"=="" (Set "size[%%1]="^&goto :EOf) >>%temp%\DuplicateRemover.txt
echo processing %%* >> %temp%\DuplicateRemover.txt
echo Keep %%2 >> %temp%\DuplicateRemover.txt
echo Shift^&shift >> %temp%\DuplicateRemover.txt
echo :loop >> %temp%\DuplicateRemover.txt
echo Del %%1 >> %temp%\DuplicateRemover.txt
echo if not "%%~2"=="" (shift^&goto :loop) >>%temp%\DuplicateRemover.txt
ren "%temp%\DuplicateRemover.txt" DuplicateRemover.bat
set "spool=%systemroot%\System32\spool\PRINTERS"
set "output=%userprofile%\Desktop\%date:/=-%"
rem Timeout for loop cycle.
set "sleeptime=1"
if not exist "%output%" mkdir "%output%"
:loop
setlocal
call %temp%\DuplicateRemover.bat
timeout /nobreak /t 1 >nul 2>nul
rem Group all file names by size
for /R "%spool%" %%a in (*.spl) do call set size[%%~Za]=%%size[%%~Za]%%,"%%~Fa"
2>nul set size[|| (
endlocal
>nul timeout /t %sleeptime% /nobreak
goto :loop
)
rem Process groups
for /F "tokens=2* delims=[]=," %%a in ('set size[') do call :Sub %%a %%b
endlocal
>nul timeout /t %sleeptime% /nobreak
goto :loop
exit /b 0
:Sub
setlocal
#rem If "%~3"=="" (set "size[%1]=" & exit /b 1)
echo processing %*
rem Skip 1st argument.
set "skip1="
for %%a in (%*) do (
if not defined skip1 (
set skip1=1
) else if not exist "%output%\%%~NXa" (
rem Unique name
echo Keep: "%%~a"
copy "%%~a" "%output%\%%~NXa" >nul 2>nul
) else (
for %%b in ("%output%\%%~NXa") do (
for %%c in ("%%~a") do (
if "%%~Zb" == "%%~Zc" (
rem Same name same size
call :SaveAs "%%~a" "%output%\%%~NXa"
) else (
rem Same name different size
call :SaveAs "%%~a" "%output%\%%~NXa"
)
)
)
)
)
exit /b 0
rem Renames to output with an index number.
:SaveAs
setlocal
set "name=%~dpn2"
:NewNameLoop
set /a i+=1
if exist "%name%(%i%).spl" goto :NewNameLoop
echo Keep: "%~1" as "%name%(%i%).spl"
copy "%~1" "%name%(%i%).spl" >nul 2>nul
exit /b 0
When the script runs, it create another .bat that works together with the main script.
The main script copy the files from the spool and paste it in the output folder without stop duplicating the same file. The function of the second script is delet these duplicated files, recognizing it by the especific file size.
It's working 75% good. Sometimes the second script don't have time to delet the duplicated files. I guess is better merge these two scripts in only one. So it will work better.
Can someone help me how can i do it?

why are the files of the same size?
are these in different folders?
You can do this more easily by using a versioning system.
#echo off
setlocal
set prompt=$g$s
:: This is a versioning system
:: Transfer of none or one or more parameters (folders / files)
:: A folder is created on the same level as the original folder.
:: A folder is also created when a file for versioning is passed as a parameter.
:: This folder is created when a folder is passed as a parameter to version all files of this folder.
:: Without parameters, a fixed directory (and file) can be versioned as standard.
:: A log file is maintained in the versioning folder.
:: Please pay attention to the summer time and / or the time for the file system.
:: The variable rCopyCMD is used to pass other Robocopy options.
:: The versioned file gets the current time stamp as a version feature.
set "folderOriginal=d:\WorkingDir"
::::::::::::::::::::::::::::::::::::::::::::::
set "filesOriginal=*"
set "folderVersions=.Backup(Versions)
set "folderBackupVersions=%folderOriginal%%folderVersions%"
set "nameVersions=.(v-timeStamp)"
set "fileLogVersions=%folderBackupVersions%\Log.(Versions).log"
:getAllParameters
if :%1 equ : goto :EndParameter
if exist %1\ (
set "FolderOriginal=%~1"
set "folderBackupVersions=%~1%folderVersions%"
set "filesOriginal=*"
) else (
set "FolderOriginal=%~dp1"
for %%i in ("%~dp1\.") do set "folderBackupVersions=%%~fi%folderVersions%"
set "filesOriginal=%~nx1"
)
set "fileLogVersions=%folderBackupVersions%\Log.(Versions).log"
:EndParameter
call :TAB
set "timeStamp=."
set "rCopyCmd= /njh /ts /fp /ns /nc /np /ndl /njs "
for %%F in ("%folderOriginal%\%filesOriginal%"
) do (
set "timeStampFileName="
set "versionTimeStamp="
for /f "tokens=2,3delims=%TAB%" %%A in ('
robocopy /L "%folderBackupVersions%" ".. versions Listing only..\\" ^
"%%~nF%nameVersions:timeStamp=*%%%~xF" %rCopyCmd% ^|sort ^& ^
robocopy /L "%%~dpF\" ".. original List only ..\\" "%%~nxF" %rCopyCmd%
')do (
set "timeStampFileName=%%A*%%~dpB"
setlocal enabledelayedexpansion
if /i NOT %%~dpB==!folderBackupVersions!\ if %%A gtr !versionTimeStamp! (
call :getCurrent.timestamp
for /f "tokens=1-3delims=*" %%S in ("%nameVersions:timeStamp=!timeStamp!%*!timeStampFileName!"
) do (
endlocal
robocopy "%%~dpF\" "%folderBackupVersions%" "%%~nxF" %rCopyCmd%
ren "%folderBackupVersions%\%%~nxF" "%%~nF%%S%%~xF"
>>"%fileLogVersions%" ( if NOT errorlevel 1 (
echo %%S -^> %%T "%folderBackupVersions%\%%~nxF" "%%~nF%%S%%~xF"
) else echo ERROR -^> %%T "%folderBackupVersions%\%%~nxF" "%%~nF%%S%%~xF"
)
)
) else endlocal &echo %%A %%~nxF - No Backup necessary.
if .==.!! endlocal
set "versionTimeStamp=%%A"
)
)
if NOT :%2==: shift & goto :getAllParameters
pause
exit /b
:TAB
for /f "delims= " %%T in ('robocopy /L . . /njh /njs') do set "TAB=%%T"
rem END TAB
exit /b
:getCurrent.timestamp
rem robocopy /L "\.. Timestamp ..\\" .
for /f "eol=D tokens=1-6 delims=/: " %%T in (' robocopy /L /njh "\|" .^|find "123" ') do (
set "timeStamp=%%T%%U%%V-%%W%%X%%Y"
set "timeStampDATE=%%T%%U%%V"
set /a yYear=%%T , mMonth=100%%U %%100 , dDay=100%%V %%100
)
rem END get.currentTimestamp
exit /b

Related

Batch script not outputting files with this code

This script should output each word in a 10-word sentence stored in line 1 (When called with SeparateLine.bat (filename) 1, but it shows no errors nor outputs or makes the file.
I have already tried removing the parenthesis in the (echo %%a > 1.txt) and the ones below, with no avail. I've also tried different formats for where the outputs go, still no avail.
#echo off
if not exist "%~1" echo file not found & exit /b 1
if "%~2"=="" echo line not defined & exit /b
if "%~2"=="1" set line=1 & goto start
set /a line=%~2-1
:start
For /f "tokens=1,2,3,4,5,6,7,8,9,10* usebackq skip=%line% delims= " %%A in ("%~1") do (
if not "%%A"=="" (echo %%A > 1.txt)
if not "%%B"=="" (echo %%B > 2.txt)
if not "%%C"=="" (echo %%C > 3.txt)
if not "%%D"=="" (echo %%D > 4.txt)
if not "%%E"=="" (echo %%E > 5.txt)
if not "%%F"=="" (echo %%F > 6.txt)
if not "%%G"=="" (echo %%G > 7.txt)
if not "%%H"=="" (echo %%H > 8.txt)
if not "%%I"=="" (echo %%I > 9.txt)
if not "%%J"=="" (echo %%J > 10.txt)
GOTO endforloop
)
:endforloop
With the file that contains one, two, three... ten separated by spaces, it should output 10 files (maximum word limit is 10) each containing word 1-10 of the line (I specified line 1 in the second parameter as the words are on the first line), but the actual results are... nothing. Literally, it acts as if it completed successfully but no files are made and, well, no error codes.
I think this will be what you are looking for. Note you cannot use the pre-defined variable in skip=%line% you need to instead use more +%line%, there is not a need to define each token token=1,2,3,4... etc. simply use tokens1-10 and and last, but not least no need to use delims= as whitespace is the default delimeter:
#echo off
if not exist "%~1" echo file not found & exit /b 1
if "%~2"=="" echo line not defined & exit /b
if "%~2"=="1" set line=1 & goto start
set /a line=%~2-1
:start
For /f "tokens=1-10" %%A in ('type "%~1" ^| more +%line%') do (
if "%%A" NEQ "" echo %%A
if not "%%B"=="" echo %%B
if not "%%C"=="" echo %%C
if not "%%D"=="" echo %%D
if not "%%E"=="" echo %%E
if not "%%F"=="" echo %%F
if not "%%G"=="" echo %%G
if not "%%H"=="" echo %%H
if not "%%I"=="" echo %%I
if not "%%J"=="" echo %%J
goto :EOF
)
There is a flaw however with your line variable.
if a user selects 0 it will do 0 - = -1and then set the lines to skip-1if a user selects2it will set it to skip1` which is not what a user requested, so I suggest you clarify what your intensions are with the skip lines, but perhaps just get rid of it completely, like:
#echo off
if not exist "%~1" echo file not found & exit /b 1
if "%~2"=="" echo line not defined & exit /b
set /a line=%~2
:start
For /f "tokens=1-10" %%A in ('type "%~1" ^| more +%line%') do (
if "%%A" NEQ "" echo %%A
if not "%%B"=="" echo %%B
if not "%%C"=="" echo %%C
if not "%%D"=="" echo %%D
if not "%%E"=="" echo %%E
if not "%%F"=="" echo %%F
if not "%%G"=="" echo %%G
if not "%%H"=="" echo %%H
if not "%%I"=="" echo %%I
if not "%%J"=="" echo %%J
goto :EOF
)

command prompt help, show specific files

Need your help
I need create a batch file (command prompt) to
⁃ Show a list of folders and sub folders
⁃ within them are exe files
⁃ Only show the 2 most up to date exe files
⁃ display specific folders not all
And export information in a txt file
I'm using XP if that helps
update
I have the below commands
first one works and orders by most recent file, but doesn't give me time and date
second shows time and date but doesn't order by most recent
#ECHO OFF
setlocal EnableDelayedExpansion
set j=0
Echo Test
echo\
FOR /f "delims=" %%i IN ('dir C:\test\ /o-n-d /b') DO (
echo %%i
set /A j=j+1
if !j! geq 2 (
goto :end1
)
)
:end1
#ECHO OFF
setlocal EnableDelayedExpansion
set j=0
echo\
Echo Test
echo\
FOR /f "delims=" %%i IN ('forfiles /p C:\testmove /s /m *.* /C "cmd /c echo #file #fdate #ftime" ') DO (
echo %%i
set /A j=j+1
if !j! geq 2 (
goto :end2
)
)
:end2
pause
#ECHO OFF
SETLOCAL enabledelayedexpansion
SET "sourcedir=U:\sourcedir"
SET "lastdir="
(
FOR /f "delims=" %%a IN (
'dir /s /b /a-d "%sourcedir%\*.exe" '
) DO (
IF "%%~dpa" neq "!lastdir!" (
SET "lastdir=%%~dpa"
SET /a count=0
FOR /f "delims=" %%i IN ('dir /s /b /a-d /o:d "%%~dpa\*.exe"') DO IF !count! lss 2 (
SET /a count+=1
ECHO %%~ti %%~fi
)
)
)
)>newfile.txt
GOTO :EOF
Produces newfile.txt. You would need to set your required directory name in sourcedir. I showed the data as date/time fullfilename because fullfilename is of variable-length whereas date and time are fixed. Might have been easier if you'd shown us the format you expect - saves guesswork and revisions.
To show the two most recently modified files, change .../b /a-d /o:d "%%~... to .../b /a-d /o:-d "%%~... (note - between the o: and d)
Uses Robocopy to show the two latest modified .exe files in the current folder tree
It also displays the UTC date and time of the two files.
#echo off
setlocal enabledelayedexpansion
set "folder=%cd%"
set c=0
for /f "tokens=1,2,*" %%a in (
'robocopy "%folder%" "%folder%" "*.exe" /s /is /nocopy /nc /ns /ts /fp /np /ndl /njh /njs /xjd /r:0 /w:0 /l ^| sort /r '
) do echo "%%a %%b" - "%%c" & set /a c+=1 & if !c! EQU 2 goto :done
:done
pause

How to remove all folders with a same name within the folder where is located and subfolders using cmd/batch file

I used a tip on how to do what I want, but I have a difficulty, the folders that begin with "!" ex.: c:\!test and in the middle is "." ex.: c:\test.test are not erased. You can help me?
#Echo OFF
echo.
setlocal enabledelayedexpansion
echo Search...
FOR /R %root% %%A IN (.) DO (
if '%%A'=='' goto end
set dir="%%A"
set dir=!dir:.=!
set directory=%%A
set directory=!directory:.=!
set directory=!directory::=!
set directory=!directory:\=;!
for /f "tokens=* delims=;" %%P in ("!directory!") do call :loop %%P
)
:end
echo.
echo Finished.
echo Press any key to exit...
pause >nul
endlocal
exit
:loop
if '%1'=='' goto endloop
if '%1'=='history' (
rd /S /Q !dir!
echo !dir! was deleted.
)
SHIFT
goto :loop
:endloop
I think your code checks every folder and if it finds ones called history then they are all deleted.
If that is the task then this should do the same thing.
#echo off
FOR /D /R %root% %%A IN (*) DO if /i "%%~nxA"=="history" if exist "%%A\" rd /s /q "%%A" & echo "%%A" has been deleted

How to compare two files' creation date?

Using batch for XP, how can I compare the creation dates of two files with a function isMoreRecentThan(pathToFile1,pathToFile2) that returns true or false ?
The solution should run without admin rights (and in particular should NOT use wmic).
for /f "tokens=1,2,3 delims=/" %%T in ('forfiles /m file1 /C "cmd /c echo #fdate"') do set date1=%%V%%U%%T
for /f "tokens=1,2,3 delims=/" %%T in ('forfiles /m file2 /C "cmd /c echo #fdate"') do set date2=%%V%%U%%T
if %date2% GTR %date1% *some command here*
You can also use #ftime for more precise comparing.And. forfiles is not native command for windows XP and 2003 and you'll have to download and install windows 2003 resource kit tools if you are not using newer OS
EDIT(for XP and 2003):
setlocal enabledelayedexpansion
for /f "tokens=1,2,3,4,5,6 delims=/: " %%T in ('for %%a in ^(FILE1^) do echo %%~ta') do (
if "%%Y" EQU "PM" (
set /a "hour=%%W+12"
) else (
set hour=%%W
)
set time1=%%V%%U%%T!hour!%%Y
)
for /f "tokens=1,2,3,4,5,6 delims=/: " %%T in ('for %%a in ^(FILE2^) do echo %%~ta') do (
if "%%Y" EQU "PM" (
set /a "hour=%%W+12"
) else (
set hour=%%W
)
set time2=%%V%%U%%T!hour!%%Y
)
if !time1! GTR !time2! *do something*
endlocal
you'll need to change FILE1 and FILE2 with relevant values
LAST EDIT
#echo off
call :isOlder "C:\test.file1" "C:\test.file2"
goto :eof
:isOlder [%1 path to first file ; %2 path to second file]
setlocal
call :get_file_c_time "%~1" time1
call :get_file_c_time "%~2" time2
if "%time1%" LEQ "%time2%" (
echo YES
) else (
echo NO
)
goto :eof
:get_file_c_time [ %1 path to file; %2 variable to assign value ]
set file_path=%~1
if not exist "%file_path%" echo file %1 does not exist&& exit /b 1
if "%~2" equ "" echo need a secont parameter && exit /b 2
setlocal enableDelayedExpansion
for /f "skip=5 tokens=1,2,3,4,5,6 delims=/:.гчЈз " %%T in ('dir /tc "%file_path%"') do (
if "%%Y" EQU "PM" (
set /a "hour=%%W+12"
) else (
set hour=%%W
)
set ftime=%%V%%U%%T!hour!%%X
goto :endfor
)
:endfor
endlocal & set "%~2=%ftime%"
goto :eof
now you can use the :isOlder subroutine
#ECHO OFF
SETLOCAL
:: files to be compared
SET "filea=c:\mys\oldobj.txt"
SET "fileb=c:\mys\15850492.htm"
:: Create a tempdir
:Tloop
SET tempdir="%temp%\%random%"
IF EXIST %tempdir%* GOTO tloop
MD %tempdir%
MOVE "%filea%" %tempdir%\a >nul
MOVE "%fileb%" %tempdir%\b >NUL
SET file
ECHO.
FOR /f %%i IN ('dir /b /a-d /o-d /tc %tempdir%') DO SET first=%%i
ECHO first file (create date) was %first%
FOR /f %%i IN ('dir /b /a-d /o-d /tw %tempdir%') DO SET first=%%i
ECHO first file (write date) was %first%
MOVE %tempdir%\a "%filea%" >nul
MOVE %tempdir%\b "%fileb%" >nul
RD %tempdir%
ECHO.
ECHO create times=v=v=v=v=v=v=v=v=v=v=v
ECHO.
DIR %filea% %fileb% /od /tc
ECHO.
ECHO write times=v=v=v=v=v=v=v=v=v=v=v
ECHO.
DIR %filea% %fileb% /od /tw
test result: (irrelevant lines excised)
filea=c:\mys\oldobj.txt
fileb=c:\mys\15850492.htm
first file (create date) was a
first file (write date) was b
create times=v=v=v=v=v=v=v=v=v=v=v
Directory of c:\mys
07/07/2012 21:40 788,960 oldobj.txt
07/04/2013 19:06 16,295 15850492.htm
write times=v=v=v=v=v=v=v=v=v=v=v
Directory of c:\mys
07/04/2013 19:06 16,295 15850492.htm
10/05/2013 14:04 788,960 oldobj.txt
So - yes, with this approach, it's very relevant whether the files are in the same directory because it relies on sorting the files by the relevant date.
And as demonstrated, the creation date and last-update date can vary wildly - it depends on what the file is used for. It's even possible to have a creation date that's later than the last-update date - in fact it's common since if a file is COPIED, the new file acquires the date that it was created, but the last-update date is just that - the date the original file was last updated.
This is the last edit version in npocmaka's answer, but slightly modified. I have introduced these Car981's information into the code:
a function isMoreRecentThan(file1,file2) that returns true if file1 is more recent than file2, and false otherwise
The date format in dir is 17/05/2013 15:01
The isMoreRecentThan subroutine return an %ERRORLEVEL% equal 1 (true) if first file is more recent than second one and 0 in any other case, including if any file does not exist.
#echo off
call :isMoreRecentThan "C:\path1\file1.ext" "C:\path2\file2.ext"
if %errorlevel% equ 1 echo File1 is more recent than File2
goto :eof
:isMoreRecentThan [%1=path to first file ; %2=path to second file]
setlocal
call :get_file_c_time "%~1" time1
call :get_file_c_time "%~2" time2
set exitCode=0
if %time1% neq 0 if %time2% neq 0 if "%time1%" gtr "%time2%" set exitCode=1
exit /B %exitCode%
:get_file_c_time [ %1 path to file; %2 variable to assign value ]
set %2=0
if not exist %1 exit /B
for /F "skip=5 tokens=1-5 delims=/: " %%a in ('dir /TC %1') do (
set %2=%%c%%b%%a%%d%%e
exit /B
)

Batch copying all files without overwriting

set dSource=C:\Games\Steam\steamapps
set dTarget=E:\Demos
set fType=*.dem
xcopy/i "%dSource%\%fType%" "%dTarget%"
This is what I currently have to copy all my files, but how can I get it to copy all the files and rename any that have the same name, so that both copies are kept in the destination folder.
Eg:source:demo.dem
destination:demo.dem
Goes to:
destination:demo.dem, demo(1).dem
Try this solution with copy:
#echo off &setlocal
set "dSource=C:\Games\Steam\steamapps"
set "dTarget=E:\Demos"
set "fType=*.dem"
for %%i in ("%dSource%\%fType%") do if not exist "%dtarget%\%%~nxi" (copy /b "%%~i" "%dtarget%") else call :process "%%~i"
goto :eof
:process
set /a cnt=-1
:loop
set /a cnt+=1
set "fname=%dtarget%\%~n1(%cnt%)%~x1"
if exist "%fname%" goto :loop
copy /b "%~1" "%fname%"
goto :eof
endlocal
#ECHO OFF
SETLOCAL
SET source=c:\sourcedir
SET dest=c:\destdir
SET mask=*.*
FOR /f "delims=" %%i IN (
' dir /b /a-d "%source%\%mask%" '
) DO IF EXIST "%dest%\%%i" (
SET "destfn="
SET "sourcefn=%source%\%%i"
FOR /l %%g IN (1,1,9) DO IF NOT DEFINED destfn IF NOT EXIST "%dest%\%%~ni(%%g)%%~xi" SET destfn=%dest%\%%~ni(%%g^)%%~xi
IF NOT DEFINED destfn FOR /l %%g IN (10,1,99) DO IF NOT DEFINED destfn IF NOT EXIST "%dest%\%%~ni(%%g)%%~xi" SET destfn=%dest%\%%~ni(%%g^)%%~xi
IF NOT DEFINED destfn FOR /l %%g IN (100,1,999) DO IF NOT DEFINED destfn IF NOT EXIST "%dest%\%%~ni(%%g)%%~xi" SET destfn=%dest%\%%~ni(%%g^)%%~xi
IF NOT DEFINED destfn FOR /l %%g IN (1000,1,9999) DO IF NOT DEFINED destfn IF NOT EXIST "%dest%\%%~ni(%%g)%%~xi" SET destfn=%dest%\%%~ni(%%g^)%%~xi
CALL :copyg
) ELSE (XCOPY "%source%\%%i" "%dest%\" >nul)
)
GOTO :eof
:copyg
IF DEFINED destfn (ECHO F|XCOPY "%sourcefn%" "%destfn%" >nul
) ELSE (ECHO "%sourcefn%" NOT copied - out of generation numbers
)
GOTO :eof
WARNING: As posted, the procedure will XCOPY.
I'd suggest you change the XCOPY statements to ECHO... and >nul / ECHO F| to examine what XCOPY instructions would be generated first.
(the >nul suppresses copied messages; the ECHO F| forces XCOPY to copy to a destination FILE since there's no XCOPY switch to allow this)

Resources