Have a need to find files in a folder that are older than X hours. Have to do this in batch because this is an older server that we don't want to load anything else on. This is based on Find out if file is older than 4 hours in Batch file, but that solution was written for only for one static filename. I have adjusted it for multiple files, and US date format, but the problem I am having in the file minutes it is picking up the 'a' or 'p' for am or pm. I have posted my partial solution below (does not perform date math and echos to screen filename and date/time values). Any ideas on how to get rid of a or p?
rem extract current date
for /f "tokens=1-5 delims=.,/ " %%a in ("%date%") do (
set day=%%c&set mon=%%b&set yr=%%d
)
REM Extract Current Time
for /f "tokens=1-5 delims=.:, " %%a in ("%time%") do (
set hr=%%a&set min=%%b
)
REM BUILD LIST OF FILES IN DIRECTORY
dir /B /O:N c:\mydir\*myfilestub*.* >list.txt
Rem LOOP THROUGH LIST OF FILES and CALL SUBROUTINE TO CHECK FILE DATE
For /F %%A in (list.txt) DO (CALL :CHECKFILE %%A)
GOTO :EOF
:CHECKFILE
REM CHECKING FILE %*
set filename=%*
rem extract file date and time
for /f "tokens=1-5 delims=.:,/ " %%a in ('"dir c:\mydir\%filename%|find "%filename%""') do (
set fday=%%a&set fmon=%%b&set fyr=%%c&set fhr=%%d&set fmin=%%e
)
ECHO %FILENAME% %fday% %fmon% %fyr% %fhr% %fmin%
GOTO :EOF
Thanks to http://www.dostips.com/DtTipsStringManipulation.php, I got the answer I was needing, just added a line below the for loop that was getting the file date
SET fmin=%fmin:~0,2%
It is nothing short of amazing what you can still accomplish with just DOS on a windows server. I know this script could be cleaned up and shortened I am sure, but it suits my purposes.
Related
Could you please help me with a command for batch file to delete the files with Name of the file.
I need to delete the files which are older than 6 months according to their File name. I need to schedule the script in Task scheduler, So it will delete the files in specific location every day which are older than 6 months from current date according to their file name.
Location of files:
K:\Bck
File Names:
Backup_2020-10-22.txt
Backup_2020-10-21.txt
Backup_2019-09-16.txt
Backup_2018-05-17.txt
Backup_2017-04-16.txt
Here is a modified version of Aacini's post, from back in 2013. I only amended it to use powershell to get today's date, instead of using the locale specific %date% variable and some changes to accomodate your environment. So I take no credit for this whatsoever.
#echo off
setlocal EnableDelayedExpansion
pushd "K:\Bck"
for /f "tokens=*" %%i in ('PowerShell -Command "& {Get-Date -format 'yyyyMMdd'}"') do set todayDate=%%i
call :DateToJDN %todayDate% todayJDN=
for /F "tokens=1-4* delims=_-" %%a in ('dir /B /A-D "Backup_*-*-*.txt"') do (
call :DateToJDN %%b%%c%%~nd fileJDN=
set /A daysOld=todayJDN - fileJDN
if !daysOld! gtr 180 (
echo File "%%a_%%b-%%c-%%d" is !daysOld! days old
del "%%a_%%b-%%c-%%d" /Q
)
)
popd
goto :eof
:DateToJDN yyyymmdd jdn=
set yyyymmdd=%1
set /A yyyy=%yyyymmdd:~0,4%, mm=1%yyyymmdd:~4,2% %% 100, dd=1%yyyymmdd:~6% %% 100
set /A a=(mm-14)/12, %2=(1461*(yyyy+4800+a))/4+(367*(mm-2-12*a))/12-(3*((yyyy+4900+a)/100))/4+dd-32075
exit /B
This will NOT yet delete anything. It will simply echo the commands to the screen. If you are sure the echo'd results resemble what you want, you can remove the echo from the line echo del "%%a_%%b_%%c_%%d" /Q
You also need to set your days accordingly in the line if !daysOld! gtr 180 (
I am working on an HR data project and after much research and even more trial and error, I have adapted the following Batch File (Windows 8.1 environment) that successfully pulls an employee’s start date from a messy text file - with many thanks to user dbenham for that prior solution (again which I adapted as follows):
#echo off
setlocal disableDelayedExpansion
set "cnt=1"
>OUTPUT.txt (
for /f "skip=219 tokens=24,25,26 delims= " %%B in (MVANHOUTEN.txt) do (
echo(%%B %%C %%D
set /a "1/(cnt-=1)" 2>nul || goto :break
)
)
:break
Where
MVANHOUTEN.txt is the input file
OUTPUT.txt file contains only:
January 21, 1991
I have a limited understanding of the intricacies of batch file programming, and despite the genius of dbenham's code which I have confirmed works 100% with my changes above, I do not know enough to alter this without breaking it. I need this batch file to do three more things but I cannot seem to make it work without destroying the functionality of the above code. Specifically, I need to:
I need to add the original text filename to the contents of the output file after the data extract. That is, I need my output file to contain:
MVANHOUTEN January 21, 1991
Instead of OUTPUT.txt, I need my output file to be named with the same filename as the input file – that is, MVANHOUTEN.txt. If this is not possible or too unweildy, adding to the original filename would be an okay alternative – e.g. MVANHOUTEN-Processed.txt)
I need a do loop as I have a directory of nearly 200,000 current and former employees and I need to batch perform the above operations for each and every file - so logically in place of "(MVANHOUTEN.TXT)" in the above, I need to find a way to loop through many *.txt files in the same directory. The results would be separate files MVANHOUTEN.txt, CMONTYBURNS.txt, DISCOSTU.txt, etc. etc. (or MVANHOUTEN-Processed.txt, CMONTYBURNS-Processed.txt, DISCOSTU-Processed.txt, etc.).
Can anybody please help me enhance my batch file above to accomplish the above without breaking the original scrub I successfully adapted from dbenham? Many thanks in advance!
untested, as I don't have your datafiles:
#echo off
setlocal disableDelayedExpansion
for /f "delims=" %%a in ('dir /b *.txt') do (
call :process %%a
)
:process
set "cnt=1"
>"%~n1-Processed.txt" (
for /f "skip=219 tokens=24,25,26 delims= " %%B in (%~nx1) do (
echo( %~n1 %%B %%C %%D
set /a "1/(cnt-=1)" 2>nul || goto :eof
)
)
Can somebody help me to adjust this script in a way that all files from the current month will be copied?
At the moment it will copy all files older than 3 days and this will not work for us.
Within a month period we create a random number of files at \\sharename\folder\source.
Here is the batch code:
set datetimef=%date:~-4%-%date:~3,2%
if not exist "\\sharename\folder\%datetimef%" mkdir "\\sharename\folder \%datetimef%"
forfiles -p "\\sharename\folder\source" -s -m *.xml /D -3 /C "cmd /c copy #file "\\sharename\folder\%datetimef%"
And it seems to work as designed.
The commented batch code below copies all files last modified this month using command xcopy (Microsoft article).
#echo off
setlocal
set "SharedFolder=\\sharename\folder"
rem Get year and month from environment variable DATE in format yyyy-mm.
rem It is required for this simple method that environment variable DATE
rem contains the date in format dd/mm/yyyy or dd.mm.yyyy with or without
rem weekday at beginning. If the format of the date string output with
rem echo %DATE% in a command prompt window is different, the line below
rem must be adapted, or the two commented lines with command wmic are
rem used because wmic returns the current date in a format independent
rem on Windows region and language settings.
set "YearMonth=%DATE:~-4%-%DATE:~-7,2%"
rem for /F "tokens=2 delims==." %%T in ('%SystemRoot%\System32\wbem\wmic.exe OS get localdatetime /VALUE') do set LocalDateTime=%%T
rem set "YearMonth=%LocalDateTime:~0,4%-%LocalDateTime:~4,2%
rem Define source and target folder.
set "TargetFolder=%SharedFolder%\%YearMonth%"
set "SourceFolder=%SharedFolder%\source"
rem Create the target folder if not already existing and verify the
rem successful creation of target folder before copying the files.
if not exist "%TargetFolder%\*" (
mkdir "%TargetFolder%"
if errorlevel 1 (
echo Error detected by %~f0:
echo.
echo Failed to create folder %TargetFolder%
echo.
echo Check availability of server and access permissions on share.
echo.
pause
endlocal
goto :EOF
)
)
rem Define date used below on command XCOPY in format mm-dd-yyyy.
set "XcopyDate=%YearMonth:~5,2%-01-%YearMonth:~0,4%
rem Copy all files last modified this month with archive attribute set.
rem The archive attribute is removed after copying on source file to prevent
rem one more copying operation of same file if this batch file is executed
rem once more this month and source file was not modified since last run.
xcopy "%SourceFolder%\*" "%TargetFolder%\" /C /D:%XcopyDate% /H /I /K /M /Q /R /Y
endlocal
You might append on command line with xcopy (SS64 article) also the options /V and /Z.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
echo /?
endlocal /?
goto /?
if /?
mkdir /?
pause /?
rem /?
set /?
setlocal /?
xcopy /?
I offer also a second version making this task the hard way without using xcopy with parameter /D.
#echo off
setlocal EnableDelayedExpansion
set "SharedFolder=\\sharename\folder"
rem Get year and month from environment variable DATE in format yyyy-mm.
rem It is required for this simple method that environment variable DATE
rem contains the date in format dd/mm/yyyy or dd.mm.yyyy with or without
rem weekday at beginning. If the format of the date string output with
rem echo %DATE% in a command prompt window is different, the line below
rem must be adapted, or the two commented lines with command wmic are
rem used because wmic returns the current date in a format independent
rem on Windows region and language settings.
set "YearMonth=%DATE:~-4%-%DATE:~-7,2%"
rem for /F "tokens=2 delims==." %%T in ('%SystemRoot%\System32\wbem\wmic.exe OS get localdatetime /VALUE') do set LocalDateTime=%%T
rem set "YearMonth=%LocalDateTime:~0,4%-%LocalDateTime:~4,2%
rem Define source and target folder.
set "TargetFolder=%SharedFolder%\%YearMonth%"
set "SourceFolder=%SharedFolder%\source"
rem Create the target folder if not already existing and verify the
rem successful creation of target folder before processing the files.
if not exist "%TargetFolder%\*" (
mkdir "%TargetFolder%"
if errorlevel 1 (
echo Error detected by %~f0:
echo.
echo Failed to create folder %TargetFolder%
echo.
echo Check availability of server and access permissions on share.
echo.
pause
endlocal
goto :EOF
)
)
rem Define and initialize two counters. First one counts how many files
rem are processed successfully and second one counts how many files
rem found to process. Finally those two counts should be always equal.
set "CountProcessed=0"
set "CountTotal=0"
rem Use command DIR to get just the names of all files in source folder
rem without path sorted reverse according to last modification date, i.e.
rem file modified last being returned first and oldest modified file being
rem at end of list.
rem For each file name returned by command DIR get last modification time.
rem It is necessary here to use command FOR for this task as DIR without
rem parameter /S returns just the file name and first FOR would not be
rem able to determine location of file to get last modification time if
rem the source folder is not the current folder which is not the case here.
rem Again it is important to know the format of last modification date/time
rem which depends on Windows region and language settings to correct extract
rem just year and month with a hyphen between to compare with year and month
rem of current date. The last modification time string must start with the
rem date in format dd/mm/yyyy or dd.mm.yyyy to use the code below as is.
rem On first file with a last modification year and month not matching
rem current year and month, the FOR loop processing the file names is
rem exited with a jump to label below the FOR loop as now all other files
rem in list should be outside of current month. This early loop exit could
rem result in a wrong behavior if a file has a last modification date in
rem future in comparison to current date.
rem Copying a file is done using command COPY. This command has some
rem limitations like not overwriting read-only files in target folder.
rem Success on copying the file is evaluated by the batch script. It
rem would be also possible to use XCOPY or ROBOCOPY with the appropriate
rem parameters to copy also hidden or read-only files if this is necessary.
for /F "delims=" %%I in ('dir /A-D /B /O-D /TW "%SourceFolder%\*" 2^>nul') do (
for %%F in ("%SourceFolder%\%%I") do set "LastModification=%%~tF"
if not "!LastModification:~6,4!-!LastModification:~3,2!" == "%YearMonth%" goto ProcessingDone
set /A CountTotal+=1
copy /B /Y "%SourceFolder%\%%I" "%TargetFolder%" >nul
if not errorlevel 1 (
set /A CountProcessed+=1
) else (
echo Failed to copy file %%I
)
)
:ProcessingDone
if "%CountTotal%" == "1" (
set "PluralTotal="
) else (
set "PluralTotal=s"
)
if "%CountProcessed%" == "1" (
set "PluralProcessed="
) else (
set "PluralProcessed=s"
)
echo.
echo Processed %CountProcessed% file%PluralProcessed% of total %CountTotal% file%PluralTotal% for %YearMonth%.
endlocal
This batch code could be used to move, modify or delete all files last modified this month by searching not case sensitive for copy, replace the command by something different and adapt the comments and output messages.
There might be a better approach, but my file names are in this format:
name_Sat Apr 11 031806 2015.mp3 (with the spaces)
In order to merge them I need to put them in order, ie. 001, 002, 003. etc.
I currently use this code to move them to a folder on the end of the each day:
#echo off
for /f "skip=1" %%x in ('wmic os get localdatetime') do if not defined MyDate set MyDate=%%x
:: variables
set SRCFOLDER=C:\srcfolder
set DESTFOLDER=C:\destfolder
set today=%MyDate:~0,4%-%MyDate:~4,2%-%MyDate:~6,2%
set backupcmd= /MOV
robocopy "%SRCFOLDER%" "%DESTFOLDER%\%today%" %backupcmd%
That produces a new folder named YYYY-MM-DD and the files are put there. I will merge them with another program, but I need to have them in a sequence by the time they were created (the time in the filename).
So the question is - How do I do that?
Thanks
If I understand correctly, files are moved to a folder based on the date when the script ran ... and not what date appears in the file name. However, you state that the files in that folder are all created on the same day and already sorted. Try adding this (untested) to your current script:
setlocal EnableDelayedExpansion
set /A Counter=0
REM Since you need folders numbered as 001, we need some padding
set /A PaddingNumber=1000
for /f "delims=" %%A in ('dir /b /a-d "%DESTFOLDER%\%today%\*"') do (
set /A Counter=!Counter!+1
set /A SequenceNumber=%PaddingNumber%+!Counter!
set FileSuffix=!SequenceNumber:~1!
ren "%%~fA" "%%~nA-!FileSuffix!%%~xA"
)
You can choose whether to have the FileSuffix at the start or end.
am struggling through these crewl batch cmds from quite long.
I need to search file (actually the installation folder of some software (XYZ) (I know there is a way to check that in registry
but I wanted an easy way to check some ABC.cmd file; if that exist give me the path of that file;
but the problem is that file also exist at various places and giving me the wrong answer.
Can some body please tell me so It can give me all file existence in least time and then I could select which I want to select with batch script.
this is my current code but It's giving the first one which it found and not my desired one:
#echo off
FOR /f "Tokens=*" %%i in ('DIR \stDesign.cmd /B /S /a-d') do (set PATH="%%~dpi")
FOR /f "Tokens=*" %%i in ('DIR \stDesign.cmd /od /b /S') do (set URL="%%~dpi")
thanks.
Well, first /a-d and /od are not switches for dir. I believe that you meant /a:d and /o:d respectively.
Apart from those errors the reason your first for statement doesn't work is because DIR \stDesign.cmd /B /S /a:d is searching for directories* called stDesign.cmd, not files.
Your second for statement is telling DIR to order the files by their creation date, but that only works for files inside the same directories, not across directories. Meaning that any matching files inside the same directory will be sorted by date, but files that exist inside seprate directories will be in the ordered that DIR found them.
Try
#echo off
echo.
REM Housekeeping: Delete any existing files left-over from previous runs
if exist "%tmp%\~.tm?" del "%tmp%\~.tm?"
REM Find the files
for %%v in (*.bat) do (
REM Extract Date, Time, Path, File Name, and Extention
for /f "tokens=1-3* delims=/ " %%w in ("%%~tdpnxv") do (
REM Change the date around so that simply sorting the lines
REM will order them by date and time.
echo %%y/%%w/%%x %%z>>%tmp%\~.tmp
)
)
REM Sort (in ascending order) and Display data
type "%tmp%\~.tmp" | sort
REM Housekeeping
del "%tmp%\~.tmp"
echo.
REM Or, if you don't want to display the time and date, replace the type line with:
#echo off
echo.
REM Housekeeping: Delete any existing files left-over from previous runs
if exist "%tmp%\~.tm?" del "%tmp%\~.tm?"
REM Find the files
for %%v in (*.bat) do (
REM Extract Date, Time, Path, File Name, and Extention
for /f "tokens=1-3* delims=/ " %%w in ("%%~tdpnxv") do (
REM Change the date around so that simply sorting the lines
REM will order them by date and time.
echo %%y/%%w/%%x %%z>>%tmp%\~.tmp
)
)
REM Sort (in ascending order) and save data to ~.tm2
type "%tmp%\~.tmp" | sort >> "%tmp%\~.tm2"
REM Extract path and file name only from ~.tm2 and display it
for /f "tokens=4* usebackq" %%x in ("%tmp%\~.tm2") do echo %%x
REM Housekeeping
del "%tmp%\~.tmp"
echo.
The first example gives an output like this:
1992\01\15 00:12:55 C:\SOMEPATH\FILE0001.EXT
2004\04\17 00:42:17 C:\ANOTHERPATH\FILE0002.EXT
2004\04\17 12:42:17 C:\MISCPATH\RANDOM\FILE0003.EXT
2012\10\15 00:12:55 C:\EXAMPLE\FILE0004.EXT
2012\01\15 00:12:55 C:\FILE0005.EXT
The 2nd example displays only the path and file names, but still ordered by date + time.
C:\SOMEPATH\FILE0001.EXT
C:\ANOTHERPATH\FILE0002.EXT
C:\MISCPATH\RANDOM\FILE0003.EXT
C:\EXAMPLE\FILE0004.EXT
C:\FILE0005.EXT
To reverse the sort order, use the /R switch with sort, like so:
type tmp.txt | sort /R
*Directories and Folders are the same thing.