Batch command date and time in file name
Asked Answered
N

15

82

I am compressing files using WinZip on the command line. Since we archive on a daily basis, I am trying to add date and time to these files so that a new one is auto generated every time.

I use the following to generate a file name. Copy paste it to your command line and you should see a filename with a Date and Time component.

echo Archive_%date:~-4,4%%date:~-10,2%%date:~-7,2%_%time:~0,2%%time:~3,2%%time:~6,2%.zip

Output

Archive_20111011_ 93609.zip

However, my issue is AM vs PM. The AM time stamp gives me time 9 (with a leading blank space) vs. 10 naturally taking up the two spaces.

I guess my issue will extend to the first nine days, first 9 months, etc. as well.

How do I fix this so that leading zeroes are included instead of leading blank spaces so I get Archive_20111011_093609.zip?

Newell answered 11/10, 2011 at 13:49 Comment(1)
I ended up using yours for a daily task, all the answers were far messier.Voltz
M
86

Another solution:

for /f "tokens=2 delims==" %%I in ('wmic os get localdatetime /format:list') do set datetime=%%I

It will give you (independent of locale settings!):

  20130802203023.304000+120
( YYYYMMDDhhmmss.<milliseconds><always 000>+/-<minutes difference to UTC>  )

From here, it is easy:

set datetime=%datetime:~0,8%-%datetime:~8,6%
20130802-203023

For Logan's request for the same outputformat for the "date-time modified" of a file:

for %%F in (test.txt) do set file=%%~fF
for /f "tokens=2 delims==" %%I in ('wmic datafile where name^="%file:\=\\%" get lastmodified /format:list') do set datetime=%%I
echo %datetime%

It is a bit more complicated, because it works only with full paths, wmic expects the backslashes to be doubled and the = has to be escaped (the first one. The second one is protected by surrounding quotes).

Megilp answered 2/8, 2013 at 18:46 Comment(10)
Brilliant! (Sample output of the wmic command: LocalDateTime=20140619212037.828000+120)Moss
not working for me %%I was unexpected at this timeOrville
@AnonymousMohit: %%Iis for use in batchfiles. If you use the line directly on the command prompt, you'll have to use %I instead.Megilp
@Megilp Do you know how to do this to get the "Date Modified" of a file in a similar format?Partiality
@Logan: I didn't until now, but I found a solution. See my edit.Megilp
wmic os get localdatetime | findstr /r "^20"Torch
This locale independent solution is ideal for my script that has to work in FIGS, Japanese and Korean!Patriarchate
There is one limitation for the names of files whose date/time you want to retrieve from using wmic: they must not contain both comma (,) and closing parenthesis ()); see also this question of mine...Archilochus
This is a good answer, but see my suggested answer for a more configurable option based on the original suggestion from Stephan in this answerJoint
@Jonathan: depends on what you need. Your solution gives values without leading zeros - that's great when you want to do math with the results, but complicates building a date-time string. What's 2020113? Thirteenth of January or Eleventh of March?Megilp
M
61

Extract the hour, look for a leading space, if found replace with a zero;

set hr=%time:~0,2%
if "%hr:~0,1%" equ " " set hr=0%hr:~1,1%
echo Archive_%date:~-4,4%%date:~-10,2%%date:~-7,2%_%hr%%time:~3,2%%time:~6,2%.zip
Mafaldamafeking answered 11/10, 2011 at 14:2 Comment(4)
Why you should search, you can simply replace all spaces with zero set hr=%hr: =0%Contreras
@jeb, why comment and not answer?Pyxie
I got Archive_b-%a%cc-_142053.zipHolophytic
@ZinanXing: because this solution depends on local settings (diffent formatting of date/time string in different countries). That's why I prefer the wmicsolution (see my answer to this question)Megilp
V
24

You should search; you can simply replace all spaces with zero set hr=%hr: =0%jeb Oct 11 '11 at 14:16

So I did:

set hr=%time:~0,2%
set hr=%hr: =0%

Then use %hr% inside whatever string you are formatting to always get a two-digit hour.

(Jeb's comment under the most popular answer worked the best for me and is the simplest. I repost it here to make it more obvious for future users.)

Vacuole answered 2/8, 2013 at 15:5 Comment(3)
It is a pity that you cannot chain the transforms. %time:~0,2: =0% would have been nice. :^(Embrocate
this seems to me to be the best solution... my congrats to the people who sent the WMIC information... mainly that indepent date format "wmic os get localdatetime" that is very useful to me.. thx again ppl... stay good...Warbler
Wow realy cool and short solution. I didn know that you can replace digit in env variables lik this :DPrefecture
M
18

As Vicky already pointed out, %DATE% and %TIME% return the current date and time using the short date and time formats that are fully (endlessly) customizable.

One user may configure its system to return Fri040811 08.03PM while another user may choose 08/04/2011 20:30.

It's a complete nightmare for a BAT programmer.

Changing the format to a firm format may fix the problem, provided you restore back the previous format before leaving the BAT file. But it may be subject to nasty race conditions and complicate recovery in cancelled BAT files.

Fortunately, there is an alternative.

You may use WMIC, instead. WMIC Path Win32_LocalTime Get Day,Hour,Minute,Month,Second,Year /Format:table returns the date and time in a invariable way. Very convenient to directly parse it with a FOR /F command.

So, putting the pieces together, try this as a starting point...

SETLOCAL enabledelayedexpansion
FOR /F "skip=1 tokens=1-6" %%A IN ('WMIC Path Win32_LocalTime Get Day^,Hour^,Minute^,Month^,Second^,Year /Format:table') DO (
  SET /A FD=%%F*1000000+%%D*100+%%A
  SET /A FT=10000+%%B*100+%%C
  SET FT=!FT:~-4!
  ECHO Archive_!FD!_!FT!.zip
 )
Millais answered 11/10, 2011 at 18:7 Comment(0)
T
18

I found the best solution for me, after reading all your answers:

set t=%date%_%time%
set d=%t:~10,4%%t:~7,2%%t:~4,2%_%t:~15,2%%t:~18,2%%t:~21,2%
echo hello>"Archive_%d%"

If AM I get 20160915_ 150101 (with a leading space and time).

If PM I get 20160915_2150101.

Tactful answered 23/9, 2016 at 2:19 Comment(3)
If you add set d=%d: =0% it'll replace that space with a zero.Blynn
Thanks CrazyPenguin set t=%date%_%time% set d=%t:~10,4%%t:~7,2%%t:~4,2%_%t:~15,2%%t:~18,2%%t:~21,2% set d=%d: =0% echo hello>"Archive_%d%"Tactful
In case anyone wonder where "set d=%d: =0%" will go, it will between line 2 and 3Tactful
R
5
@For /F "tokens=1,2,3,4 delims=/ " %%A in ('Date /t') do @(

Set DayW=%%A

Set Day=%%B

Set Month=%%C


Set Year=%%D


Set All=%%D%%B%%C
)
"C:\Windows\CWBZIP.EXE" "c:\transfer\ziptest%All%.zip" "C:\transfer\MB5L.txt"

This takes MB5L.txt and compresses it to ziptest20120204.zip if run on 4 Feb 2012

Raster answered 4/2, 2012 at 19:29 Comment(0)
B
4

You can add leading zeroes to a variable (value up to 99) like this in batch: IF 1%Var% LSS 100 SET Var=0%Var%

So you'd need to parse your date and time components out into separate variables, treat them all like this, then concatenate them back together to create the file name.

However, your underlying method for parsing date and time is dependent on system locale settings. If you're happy for your code not to be portable to other machines, that's probably fine, but if you expect it to work in different international contexts then you'll need a different approach, for example by reading out the registry settings:

HKEY_CURRENT_USER\Control Panel\International\iDate
HKEY_CURRENT_USER\Control Panel\International\iTime
HKEY_CURRENT_USER\Control Panel\International\iTLZero

(That last one controls whether there is a leading zero on times, but not dates as far as I know).

Benevolence answered 11/10, 2011 at 14:3 Comment(1)
I want to give you another +1 for locale settings. I'm doing this on my company servers, changing locale is not an option on these servers so I'm fairly safe. The date+time is purely an indication of when the job ran.Newell
R
2

From the answer above, I have made a ready-to-use function.

Validated with french local settings.

:::::::: PROGRAM ::::::::::

call:genname "my file 1.txt"
echo "%newname%"
call:genname "my file 2.doc"
echo "%newname%"

echo.&pause&goto:eof
:::::::: FUNCTIONS :::::::::

:genname
    set d1=%date:~-4,4%
    set d2=%date:~-10,2%
    set d3=%date:~-7,2%
    set t1=%time:~0,2%
    ::if "%t1:~0,1%" equ " " set t1=0%t1:~1,1%
    set t1=%t1: =0%
    set t2=%time:~3,2%
    set t3=%time:~6,2%
    set filename=%~1
    set newname=%d1%%d2%%d3%_%t1%%t2%%t3%-%filename%
goto:eof
Railey answered 12/2, 2015 at 11:16 Comment(0)
A
1

As others have already pointed out, the date and time formats of %DATE% and %TIME% (as well as date /T and time /T) are locale-dependent, so extracting the current date and time is always a nightmare, and it is impossible to get a solution that works with all possible formats since there are hardly any format limitations.


But there is another problem with a code like the following one (let us assume a date format like MM/DD/YYYY and a 12 h time format like h:mm:ss.ff ap where ap is either AM or PM and ff are fractional seconds):

rem // Resolve AM/PM time:
set "HOUR=%TIME:~,2%"
if "%TIME:~-2%" == "PM" if %HOUR% lss 12 set /A "HOUR+=12"
if "%TIME:~-2%" == "AM" if %HOUR% equ 12 set /A "HOUR-=12"
rem // Left-zero-pad hour:
set "HOUR=0%HOUR%"
rem // Build and display date/time string:
echo %DATE:~-4,4%%DATE:~0,2%%DATE:~3,2%_%HOUR:~-2%%TIME:~3,2%%TIME:~6,2%

Each instance of %DATE% and %TIME% returns the date or time value present at the time of its expansion, therefore the first %DATE% or %TIME% expression might return a different value than the following ones (you can prove that when echoing a long string containing a huge amount of such, preferrably %TIME%, expressions).

You could improve the aforementioned code to hold a single instance of %DATE% and %TIME% like this:

rem // Store current date and time once in the same line:
set "CURRDATE=%DATE%" & set "CURRTIME=%TIME%"
rem // Resolve AM/PM time:
set "HOUR=%CURRTIME:~,2%"
if "%CURRTIME:~-2%" == "PM" if %HOUR% lss 12 set /A "HOUR+=12"
if "%CURRTIME:~-2%" == "AM" if %HOUR% equ 12 set /A "HOUR-=12"
rem // Left-zero-pad hour:
set "HOUR=0%HOUR%"
rem // Build and display date/time string:
echo %CURRDATE:~-4,4%%CURRDATE:~0,2%%CURRDATE:~3,2%_%HOUR:~-2%%CURRTIME:~3,2%%CURRTIME:~6,2%

But still, the returned values in %DATE% and %TIME% could reflect different days when executed at midnight.

The only way to have the same day in %CURRDATE% and %CURRTIME% is this:

rem // Store current date and time once in the same line:
set "CURRDATE=%DATE%" & set "CURRTIME=%TIME%"
rem // Resolve AM/PM time:
set "HOUR=%CURRTIME:~,2%"
if "%CURRTIME:~-2%" == "PM" if %HOUR% lss 12 set /A "HOUR+=12"
if "%CURRTIME:~-2%" == "AM" if %HOUR% equ 12 set /A "HOUR-=12"
rem // Fix date/time midnight discrepancy:
if not "%CURRDATE%" == "%DATE%" if %CURRTIME:~0,2% equ 0 set "CURRDATE=%DATE%"
rem // Left-zero-pad hour:
set "HOUR=0%HOUR%"
rem // Build and display date/time string:
echo %CURRDATE:~-4,4%%CURRDATE:~0,2%%CURRDATE:~3,2%_%HOUR:~-2%%CURRTIME:~3,2%%CURRTIME:~6,2%

Of course the occurrence of the described problem is quite improbable, but at one point it will happen and cause strange unexplainable failures.


The described problem cannot occur with the approaches based on the wmic command as described in the answer by user Stephan and in the answer by user PA., so I strongly recommend to go for one of them. The only disadvantage of wmic is that it is way slower.

Archilochus answered 16/7, 2019 at 13:28 Comment(0)
C
0

Your question seems to be solved, but ...

I'm not sure if you take the right solution for your problem.
I suppose you try to compress each day the actual project code.

It's possible with ZIP and 1980 this was a good solution, but today you should use a repository system, like subversion or git or ..., but not a zip-file.

Ok, perhaps it could be that I'm wrong.

Contreras answered 11/10, 2011 at 14:14 Comment(2)
You just dated yourself with the 1980 comment, old timer. Now read my question one more time and you'll see that I never once mentioned that I'm zipping up any code. To make it clear, I'm archiving incoming files that are used in an ETL process.Newell
Yes, you never mentioned what you are zipping, that's why I only guessed. And as SO is much used by coders, I guessed wrongly it could be code. And yes I'm an old timer (but this is only a point of view)Contreras
D
0

I realise this is a moot question to the OP, but I just brewed this, and I'm a tad proud of myself for thinking outside the box.

Download gawk for Windows at http://gnuwin32.sourceforge.net/packages/gawk.htm .... Then it's a one liner, without all that clunky DOS batch syntax, where it takes six FOR loops to split the strings (WTF? That's really really BAD MAD AND SAD! ... IMHO of course)

If you already know C, C++, Perl, or Ruby then picking-up AWK (which inherits from the former two, and contributes significantly to the latter two) is a piece of the proverbial CAKE!!!

The DOS Batch command:

echo %DATE% %TIME% && echo %DATE% %TIME% | gawk -F"[ /:.]" "{printf(""""%s%02d%02d-%02d%02d%02d\n"""", $4, $3, $2, $5, $6, $7);}"

Prints:

Tue 04/09/2012 10:40:38.25
20120904-104038

Now that's not quite the full story... I'm just going to be lazy and hard-code the rest of my log-file-name in the printf statement, because it's simple... But if anybody knows how to set a %NOW% variable to AWK's output (yeilding the guts of a "generic" now function) then I'm all ears.


EDIT:

A quick search on Stack Overflow filled in that last piece of the puzzle, Batch equivalent of Bash backticks.

So, these three lines of DOS batch:

echo %DATE% %TIME% | awk -F"[ /:.]" "{printf(""""%s%02d%02d-%02d%02d%02d\n"""", $4, $3, $2, $5, $6, $7);}" >%temp%\now.txt
set /p now=<%temp%\now.txt
echo %now%

Produce:

20120904-114434

So now I can include a datetime in the name of the log-file produced by my SQL Server installation (2005+) script thus:

sqlcmd -S .\SQLEXPRESS -d MyDb -e -i MyTSqlCommands.sql >MyTSqlCommands.sql.%now%.log

And I'm a happy camper again (except life was still SOOOOO much easier on Unix).

Dielle answered 4/9, 2012 at 0:57 Comment(0)
J
0

I prever to use this over the current accepted answer from Stephan as it makes it possible to configure the timestamp using named parameters after that:

for /f %%x in ('wmic path win32_utctime get /format:list ^| findstr "="') do set %%x

It will provide the following parameters:

  • Day
  • DayOfWeek
  • Hour
  • Milliseconds
  • Minute
  • Month
  • Quarter
  • Second
  • WeekInMonth
  • Year

You can then configure your format like so:

SET DATE=%Year%%Month%%Day%

Joint answered 14/4, 2020 at 7:17 Comment(3)
Will this work regardless of any date format customizations, or regional settings, in Windows?Nace
This will return values without leading zeros for all variables. That might be advantageous when you want to calculate but makes it messy to generate a valid date/time string. also see my commentMegilp
Yes, @dylan-kinnet I expect this to work on any locale as it is parsing the following output from wmic: ``` wmic path win32_utctime get /format:list Day=7 DayOfWeek=1 Hour=8 Milliseconds= Minute=55 Month=3 Quarter=1 Second=50 WeekInMonth=2 Year=2022 ```Joint
P
0

So you want to generate date in format YYYYMMDD_hhmmss. As %date% and %time% formats are locale dependant you might need more robust ways to get a formatted date.

Here's one option:

@if (@X)==(@Y) @end /*
    @cscript //E:JScript //nologo "%~f0"
    @exit /b %errorlevel%
@end*/
var todayDate = new Date();
todayDate = "" + 
    todayDate.getFullYear() + 
    ("0" + (todayDate.getMonth() + 1)).slice(-2) +
    ("0" + todayDate.getDate()).slice(-2) + 
    "_" + 
    ("0" + todayDate.getHours()).slice(-2) +
    ("0" + todayDate.getMinutes()).slice(-2) +
    ("0" + todayDate.getSeconds()).slice(-2) ;
WScript.Echo(todayDate);

and if you save the script as jsdate.bat you can assign it as a value :

for /f %%a in ('jsdate.bat') do @set "fdate=%%a"
echo %fdate%

or directly from command prompt:

for /f %a in ('jsdate.bat') do @set "fdate=%a"

Or you can use powershell which probably is the way that requires the less code:

for /f %%# in ('powershell Get-Date -Format "yyyyMMdd_HHmmss"') do set "fdate=%%#"
Primula answered 12/11, 2020 at 16:50 Comment(0)
S
0

Adding other options to this list of answers.

you could have replaced empty space with a 0 something like echo %time: =0%

but that is still dependent, move that code to a buddy's PC in some other random place and you'll get funny outputs. So you can incorporate powershell's Get-Date:

for /f "tokens=*" %%i in ('PowerShell -Command "Get-Date -format 'yyyymmdd_HHmmss'"') do echo %%i.zip"
Subarctic answered 13/4, 2021 at 21:23 Comment(0)
T
-1

A space is legal in file names. If you put your path and file name in quotes, it may just fly. Here's what I'm using in a batch file:

svnadmin hotcopy "C:\SourcePath\Folder" "f:\DestPath\Folder%filename%"

It doesn't matter if there are spaces in %filename%.

Toddtoddie answered 14/10, 2016 at 14:7 Comment(2)
How is this relevant with the question about date and time?Contreras
Valid question. The OP was concerned about no spaces in a file name but does not say why. This could be for aesthetic reasons. But they may be creating the file name in a script, and a file name with a space in it would be treated like two parameters, unless quoted.Toddtoddie

© 2022 - 2024 — McMap. All rights reserved.