Generate unique file name with timestamp in batch script - windows

In my .bat file I want to generate a unique name for files/directories based on date-time.
e.g.
Build-2009-10-29-10-59-00
The problem is that %TIME% won't do because it contains characters that are illegal in filename (e.g. :).
Is there something like tr in batch files?
Any other ideas how to solve this (that don't require extra command line utilities aside from the batch interpreter)?

EDIT: A better way of doing this is to take a date/time string that has a defined and unchanging format instead of using the locale-defined ones from %date% and %time%. You can use the following to get it:
for /f "skip=1" %%x in ('wmic os get localdatetime') do if not defined mydate set mydate=%%x
It yields something like 20120730203126.530000+120 and you can use that to construct your file names.
(Old answer below)
You can simply replace the offending character with an empty string:
echo %time::=%
The syntax %var:str1=str2% takes the environment variable (or pseudo-variable in case of %TIME% and replaces str1 by str2. If nothing follows after the equals sign then str1 is simply deleted.
In your specific case I think you'd want the following:
rem cut off fractional seconds
set t=%time:~0,8%
rem replace colons with dashes
set t=%t::=-%
set FileName=Build-%date%-%t%
A more brute-force way in case you don't know whether colons are used (but the order of the time would be the same):
set FileName=Build-%date%-%time:~0,2%-%time:~3,2%-%time:~6,2%
All preceding things, however, assume that you use standard ISO 8601 date format, i. e. 2009-10-29. I'd assume this as simply normal, but some people use other formats so be careful. But since you didn't ask about the date I was assuming you didn't have a problem there.

Following up on #Joey's and #Kees' answers to make them instantly usable.
On the command line:
FOR /f %a IN ('WMIC OS GET LocalDateTime ^| FIND "."') DO SET DTS=%a
SET DateTime=%DTS:~0,4%-%DTS:~4,2%-%DTS:~6,2%_%DTS:~8,2%-%DTS:~10,2%-%DTS:~12,2%
echo %DateTime%
In a BAT file:
#echo off
REM See http://stackoverflow.com/q/1642677/1143274
FOR /f %%a IN ('WMIC OS GET LocalDateTime ^| FIND "."') DO SET DTS=%%a
SET DateTime=%DTS:~0,4%-%DTS:~4,2%-%DTS:~6,2%_%DTS:~8,2%-%DTS:~10,2%-%DTS:~12,2%
echo %DateTime%
Example output:
2014-10-21_16-28-52

I use this to create a unique file name for the execution of the batch file.
REM ****Set up Logging ****
For /f "tokens=2-4 delims=/ " %%a in ('date /t') do (set mydate=%%c-%%a-%%b)
For /f "tokens=1-2 delims=/:" %%a in ("%TIME%") do (set mytime=%%a%%b)
set mytime=%mytime: =0%
set Logname="PCCU_%mydate%_%mytime%.log"
Echo. >>%Logname% 2>>&1
Echo.=================== >>%Logname% 2>>&1
I had to add the line
set mytime=%mytime: =0%
because I had the same problem where a blank was being entered before 10 AM, now I get 09 instead of 9. I also reuse the %mydate% and %mytime% variable for other files that I create with this script so that they all have the same date time stamp.

This routine, actually only one line, works on every system set to any date or time format.
Output of line 1 is in format 20140725095527.710000+120
The actual date/time format you need is determined in line 2. You can format it however you want.
Just add the resulting DateTime variable to your filename ie. Filename_%DateTime%.log
::=======================================================================
::== CREATE UNIQUE DateTime STRING IN FORMAT YYYYMMDD-HHMMSS
::=======================================================================
FOR /f %%a IN ('WMIC OS GET LocalDateTime ^| FIND "."') DO SET DTS=%%a
SET DateTime=%DTS:~0,8%-%DTS:~8,6% | REM OUTPUT = 20140725-095527

I made this universal, Will work on any environment where date format may be different.
echo off
if not exist "C:\SWLOG\" mkdir C:\SWLOG
cd C:\SWLOG\
cmd /c "powershell get-date -format ^"{yyyyMMdd-HHmmss}^""> result.txt
REM echo %time% > result.txt
type result.txt > result1.txt
set /p filename=<result1.txt
echo %filename%
del C:\SWLOG\result.txt
del C:\SWLOG\result1.txt

To make the code in the previous example work, I needed to adjust slightly. I presume this is because my PC is using a UK date format. To get back "2014-04-19" in mydate I needed:
For /f "tokens=1-3 delims=/ " %%a in ('date /t') do (set mydate=%%c-%%b-%%a)
Below I've pasted my total script, and included an example of how to use the filename
For /f "tokens=1-3 delims=/ " %%a in ('date /t') do (set mydate=%%c-%%b-%%a)
For /f "tokens=1-2 delims=/:" %%a in ("%TIME%") do (set mytime=%%a%%b)
set mytime=%mytime: =0%
set Logname="c:\temp\LogFiles\MyLogFile_%mydate%_%mytime%.log"
Robocopy \\sourceserver\Music H:\MyBackups\Music /MIR /FFT /Z /XA:H /W:5 /np /fp /dcopy:T /unilog:%Logname% /tee
Hope this helps!

Datetime stamp:
#echo off
for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a"
set "YY=%dt:~2,2%" & set "YYYY=%dt:~0,4%" & set "MM=%dt:~4,2%" & set "DD=%dt:~6,2%"
set "HH=%dt:~8,2%" & set "Min=%dt:~10,2%" & set "Sec=%dt:~12,2%"
rem set "datestamp=%YY%%MM%%DD%" & set "timestamp=%HH%%Min%%Sec%"
set "datestamp=%YYYY%%MM%%DD%"
set "timestamp=%HH%%Min%%Sec%"
set unique_number=%datestamp%%timestamp%
echo %unique_number%

If you can guarantee that the machine has a specific version of Python installed on it and accessible in the system's PATH, you can use this solution:
FOR /F "tokens=* USEBACKQ" %%F IN (`python -c "import datetime; print
datetime.datetime.now().replace(microsecond=0).isoformat().replace(':', '-')"`) DO (
SET TIMESTAMP=%%F
)
ECHO %TIMESTAMP%
This will put the current local ISO-8601(ish) date representation into a %TIMESTAMP% variable and echo it out, like so:
2017-05-25T14:54:37
I've put replace(':', '-') after the isoformat() so that the resultant string can be used in a filename or directory, since : is a forbidden character in the Windows filesystem.

Related

Having trouble with a script to find the date and time in a batch file

So, I have a script to log the date and time in a text file:
for /f "tokens=2 delims==" %%G in ('wmic os get localdatetime /value') do set datetime=%%G
set year=%datetime:~0,4%
rem pause
set month=%datetime:~4,2%
set day=%datetime:~6,2%
set /a day2=day+5
echo %year%/%month%/%day2%> C:\WLT\Init\lastoptim.txt
And a similar one in a script that runs on startup:
for /f "tokens=2 delims==" %%G in ('type C:\WLT\Init\lastoptim.txt') do set datetime2=%%G
set year=2%datetime2:~0,4%
rem pause
set month2=%datetime2:~4,2%
set day2=%datetime2:~6,2%
set /a day3=day2+1
echo %year2%/%month2%/%day3%> lastoptim2.txt
echo %year2%/%month2%/%day3%
But it doesn’t work. What I need is a script to extract a date from %date% into a text file, and then another one to take that date, see if the current date is X number of days later, and if it is, then run a command.
Would like this script to be entirely dependent on cmd, because this is going to be used on systems as far back as XP. Using an external app (e.g. an exe that prints out the date in a specific format) would be fine.
Your question still not clear for me, but if you want to add one day or one month for your dates, here is an example :
#echo off
Title Manipulate DATES WITH BATCH
#for /f "tokens=* delims=" %%a in ('wmic os get LocalDateTime /value') do for /f "tokens=* delims=" %%# in ("%%a") do set "%%#"
:: Store the local date inside a variable
set "CurrentDateTime=%LocalDateTime%"
set "CurrentDate=%CurrentDateTime:~0,4%/%CurrentDateTime:~4,2%/%CurrentDateTime:~6,2%"
:: Here Adding One day
#for /f %%a in ('Powershell -C "(Get-Date).AddDays(1).ToString('yyyy/MM/dd')"') do set "NextDay=%%a"
:: Here adding 1 month
#for /f %%a in ('Powershell -C "(Get-Date).AddMonths(1).ToString('yyyy/MM/dd')"') do set "NextMonth=%%a"
echo( CurrentDate : %CurrentDate%
echo( NextDay : %NextDay%
echo( NextMonth : %NextMonth%
pause

How to exclude the bat-file itself from the renaming

following scenario:
i have written a batch script whitch adds the datestamp to the filename. There are lots of different file-types in the folder.
#echo off
for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a"
set "YY=%dt:~2,2%" & set "YYYY=%dt:~0,4%" & set "MM=%dt:~4,2%" & set "DD=%dt:~6,2%"
set "datestamp=%YYYY%-%MM%-%DD%_"
:: naming like ISO 8601
pause
for %%i in (*.*) do ren %%i %datestamp%%%i*
is there a good way to exclude the bat-file itself from the renaming? It would be good enought if there is a way to exclude all .bat-files.
Your trailing * in the REN statement is not doing anything - it is not needed.
You should enclose the REN filenames in quotes in case you run into names with spaces.
Filtering out (skipping) your running batch file is easy. DIR /B can be piped to FINDSTR /V to get a list of files except for the running script. %~nx0 gives the file name and extension of the running script. FOR /F is used to capture and process the list of files.
for /f "eol=: delims=" %%F in ('dir /b /a-d ^| findstr /vixc:"%~nx0"') do ren "%%F" "%datestamp%%%F"

How to get date in BAT file

I need to get today date in Window *.bat file. After it I would like to get day, month and year. How can I do this?
I can't use PowerShell
This will give you DD MM YYYY YY HH Min Sec variables and works on any Windows machine from XP Pro and later.
#echo off
for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a"
set "YY=%dt:~2,2%" & set "YYYY=%dt:~0,4%" & set "MM=%dt:~4,2%" & set "DD=%dt:~6,2%"
set "HH=%dt:~8,2%" & set "Min=%dt:~10,2%" & set "Sec=%dt:~12,2%"
set "datestamp=%YYYY%%MM%%DD%" & set "timestamp=%HH%%Min%%Sec%"
set "fullstamp=%YYYY%-%MM%-%DD%_%HH%-%Min%-%Sec%"
echo datestamp: "%datestamp%"
echo timestamp: "%timestamp%"
echo fullstamp: "%fullstamp%"
pause
You get and format like this
for /f "tokens=1-4 delims=/ " %%i in ("%date%") do (
set dow=%%i
set month=%%j
set day=%%k
set year=%%l
)
set datestr=%month%_%day%_%year%
echo datestr is %datestr%
Note: Above only works on US locale. It assumes the output of echo %date% looks like this: Thu 02/13/21. If you have different Windows locale settings, you will need to modify the script based on your configuration.
%date% will give you the date.
%time% will give you the time.
The date and time /t commands may give you more detail.
Locale-independent one liner to get any date format you like. I use it to generate archive names. Back quote (`) option is needed because PowerShell command line is using single quotes (').
:: Get date in 'yyyyMMdd_HHmm' format to use with file name.
FOR /f "usebackq" %%i IN (`PowerShell ^(Get-Date^).ToString^('yyyyMMdd_HHmm'^)`) DO SET DTime=%%i
:: Get yesterday date in 'yyyy-MM-dd' format.
FOR /f "usebackq" %%i IN (`PowerShell ^(Get-Date^).AddDays^(-1^).ToString^('yyyy-MM-dd'^)`) DO SET DTime=%%i
:: Show file name with the date.
echo Archive.%DTime%.zip
set datestr=%date%
set result=%datestr:/=-%
#echo %result%
pause
This will give you the date in this format mmddyyyy saved into %today%, assuming your regional settings have you in the US locale.
FOR /f "tokens=2-4 delims=/ " %%a IN ("%date%") DO SET today=%%a%%b%%c
In my case I was looking to create a folder with todays date, like this...
mkdir C:\Users\LKrell\Documents\%today%

Windows Batch script save file as date/time

Im using this code on a windows batch script:
FOR /F "TOKENS=1* DELIMS= " %%A IN ('DATE/T') DO SET CDATE=%%B
FOR /F "TOKENS=1,2 eol=/ DELIMS=/ " %%A IN ('DATE/T') DO SET mm=%%B
FOR /F "TOKENS=1,2 DELIMS=/ eol=/" %%A IN ('echo %CDATE%') DO SET dd=%%B
FOR /F "TOKENS=2,3 DELIMS=/ " %%A IN ('echo %CDATE%') DO SET yyyy=%%B
SET date=%dd%%mm%%yyyy%
echo New folder name %date%
but the folder name is just 07on
i need to be able to save the file as dd-mm-yy h:m:s
I'm really not sure what you're trying to accomplish, but you might want to look at something like this:
Running this today (from a command prompt)
C:\>date
The current date is: Thu 07/04/2013
Enter the new date: (mm-dd-yy)
C:\>SET Today=%Date:~10,4%-%Date:~4,2%-%Date:~7,2%
C:\>ECHO %Today%
Produces
2013-07-04
It works like this:
SET Today=%Date:~10,4%-%Date:~4,2%-%Date:~7,2%
^ ^ ^ ^ ^
| | | | |
Year | Dash Month Day
|
Number of chars
You can get the time values the same way, replacing the %Date% with %Time% and adjusting the offsets the way you need to get the format you want to get.
You might also find this similar answer I posted helpful if you want to separate the year, month, and day into separate values.
This is a robust method to get date and time rather than rely on the PC regional settings. Requires XP Pro and higher.
#echo off
for /f "delims=" %%a in ('wmic OS Get localdatetime ^| find "."') do set dt=%%a
set datestamp=%dt:~0,8%
set timestamp=%dt:~8,6%
set YYYY=%dt:~0,4%
set MM=%dt:~4,2%
set DD=%dt:~6,2%
set HH=%dt:~8,2%
set Min=%dt:~10,2%
set Sec=%dt:~12,2%
set stamp=%YYYY%-%MM%-%DD%_%HH%-%Min%-%Sec%
echo stamp: "%stamp%"
echo datestamp: "%datestamp%"
echo timestamp: "%timestamp%"
pause
Its easy. Just enter echo %time% or echo %date% and it will tell you. Hope it helps!

Format file date YYYYMMDD in batch

I've been working on some code in a batch file that evaluates two file dates. If one date is greater than the other then it runs another bat file. What I want to do is format the two dates as YYYYMMDD so that I can use the GTR (greater than).
The code is below but and it works if I use == (equal) because it's evaluating the string. I only want to know if one file date is greater than the other file date.
I'm not asking for someone to amend the code below but if you can show me how to format the dates I would be very grateful.
set Fileone=File1.txt
set FileTwo=File2.txt
pushd "D:\Board\Broadcast\FA_Report8_A"
FOR %%f IN (%FileOne%) DO SET filedatetime=%%~tf
FOR %%f IN (%FileTwo%) DO SET filedatetime2=%%~tf
SET filedatetime2=%year%%month%%day%
IF %filedatetime:~0, 10% GTR %filedatetime2:~0, 10% (
echo FileOne Greater - run bat
timeout /t 20 /nobreak
goto Finish
) else (
echo FileOne not Greater - Finish
goto Finish
)
:Finish
echo finished
pause
It's not portable between machines with different date formats but the simplest way is to use a substring: %var:~STARTPOS,LENGTH%
set filedatetime=14/06/2012 12:26
set filedatetime=%filedatetime:~6,4%%filedatetime:~3,2%%filedatetime:~0,2%
echo "%filedatetime%"
"20120614"
You can separate a date in its parts with a FOR /F command:
set filedatetime=14/06/2012 12:26
for /F "tokens=1-3 delims=/ " %%a in ("%filedatetime%") do (
set filedatetime=%%c%%b%%a
)
This form prevents you to make a mistake in the position or size of each substring, and is very easy to change the order of the parts. For example, if your date is MM/DD/YYYY:
set filedatetime=%%c%%a%%b
Type FOR /? for further details.
The layout for date variable strings in the system can be assumed by settings from the user, by regional and/or language, so, date is not 100% predictable layout to work with.
Try using wmic OS Get localdatetime /value because the result is 100% predictable:
LocalDateTime=20190609123708.733000-180
SO, if you use in for loop, adding 2 delimiters like =., (equal and dot), you go getting this string output:
20190609123708.
The layout from this command is predictable and works independent of regional settings, user settings or system language, so, the command will always return:
set _date=20190609123708
rem :: %_date:~0,4%_%_date:~4,2%_%_date:~6,2%
rem :: year:2019 | month:06 | day:09
In bat file:
#echo off & for /f "tokens=2delims==." %%i in ('wmic OS Get localdatetime /value ^|findstr /r [0-9]')do set "_date=%%i" & echo/%_date:~0,4%%_date:~4,2%%_date:~6,2%
In command line:
for /f "tokens=2delims==." %i in ('wmic OS Get localdatetime /value ^|findstr /r [0-9]')do set "_data=%i" & mkdir %_date:~0,4%_%_date:~4,2%_%_date:~6,2%
This commands result ::
20190609
May I can also suggest:
wmic Path Win32_LocalTime Get Day,Month,Year
In looping for:
#echo off & setlocal enabledelayedexpansion & set "_do=wmic Path Win32_LocalTime Get Day^,Month^,Year"
for /f "tokens=1-3delims= " %%a in ('!_do!^|findstr /r [0-9]')do set "y=%%c" & set "d=0%%a" & set "m=0%%b"
echo/!y!!m:~-2!!d:~-2! >nul
Result:
Day Month Year
9 6 2019
%%a %%b %%c
The difference is no zero in number for month/day less equal 9, so, you can use this bat to put leading zero in this case:
#echo off & setlocal enabledelayedexpansion & set "_do=wmic Path Win32_LocalTime Get Day^,Month^,Year"
for /f "tokens=1-3delims= " %%a in ('!_do!^|findstr /r [0-9]')do set "y=%%c" & set "d=0%%a" & set "m=0%%b"
echo/!y!!m:~-2!!d:~-2!
Result in YearMonthDay:
20190609
Obs.: In PowerShell, the layout can be customized simple by:
ToString("yyyyMMdd")
The strings can be set with ToString.
Sample: yyyy-MM-dd, dd-MM-yyyy, MM-dd-yyyy, MM_dd_yyyy, yyyy_MM_dd, etc..
The Powershell command:
$(Get-Date).ToString("yyyyMMdd")
Result:
2010609
See more about date variable layout output in batch here:
Safe way to get current day month and year in batch
Parsing Dates in Batch Files & Regional Settings / Locale
Update - How applying the comments/observations above in your bat, so, if I understood your code in this question:
#echo off & setlocal enabledelayedexpansion
set "Fileone=File1.txt" & set "FileTwo=File2.txt"
set "_both=!FileOne!-!FileTwo!" & rem cd /d "D:\Board\Broadcast\FA_Report8_A"
set "_path_back=%__CD__%" & rem :: you can use this "%__CD__%" or pushd "D:\Board\Broadcast\FA_Report8_A"
for /f "tokens=2delims==." %%i in ('wmic OS Get localdatetime /value ^|findstr /r [0-9]')do set "_date=%%i"
set _now=!_date:~0,4!!_date:~4,2!!_date:~6,2! & for /f "tokens=1*delims=-" %%i in ('echo/!_both!')do (
call :compare "%%~fi" & call :compare "%%~fj" & if !_dt_file_2! gtr !_dt_file_2! (
echo/ FileOne Greater - run bat & timeout /t 20 /nobreak & goto :run_bat
) else (echo/ FileOne not Greater - Finish & goto Finish)
)
:compare
set "_file=" & set "_file=%~1"
for /f "tokens=1delims=. " %%d in ('wmic datafile where name^='!_file:\=\\!' get LastModified ^|findstr /v "LastModified"')do (
if "!_dt_file_1!./" == "./" (set _dt_file_2=%%d) else (set _dt_file_2=%%d)
) & exit /b
:run_bat
call the_bat_to_run.cmd
:Finish
echo/Finished
So sorry by my limited English...

Resources