Creating a file name as a timestamp in a batch job

Viewed 332890

We have a batch job that runs every day and copies a file to a pickup folder. I want to also take a copy of that file and drop it into an archive folder with the filename

 yyyy-MM-dd.log

What's the easiest way to do this in a Windows batch job?

I'm basically looking for an equivalent of this Unix command:

cp source.log `date +%F`.log
20 Answers
CP source.log %DATE:~-4%-%DATE:~4,2%-%DATE:~7,2%.log

But it's locale dependent. I'm not sure if %DATE% is localized, or depends on the format specified for the short date in Windows.

Here is a locale-independent way to extract the current date from this answer, but it depends on WMIC and FOR /F:

FOR /F %%A IN ('WMIC OS GET LocalDateTime ^| FINDSTR \.') DO @SET B=%%A
CP source.log %B:~0,4%-%B:~4,2%-%B:~6,2%.log

This worked for me and was a filename-safe solution (though it generates a MM-dd-YYYY format):

C:\ set SAVESTAMP=%DATE:/=-%@%TIME::=-%
C:\ set SAVESTAMP=%SAVESTAMP: =%
C:\ set SAVESTAMP=%SAVESTAMP:,=.%.jpg
C:\ echo %SAVESTAMP%
11-04-2012@20-52-42.79.jpg

The first command takes a DATE and replaces / with -, takes the TIME and replaces : with -, and combines them into DATE@TIME format. The second set statement removes any spaces, and the third set replaces , with . and appends the .jpg extension.

The above code is used in a little script that pulls images from a security IP Camera for further processing:

:while
set SAVESTAMP=%DATE:/=-%@%TIME::=-%
set SAVESTAMP=%SAVESTAMP: =%
set SAVESTAMP=%SAVESTAMP:,=.%.jpg
wget-1.10.2.exe --tries=0 -O %SAVESTAMP% http://admin:<password>@<ip address>:<port>/snapshot.cgi
timeout 1
GOTO while

Because the idea of tearing %DATE% and %TIME% apart and mashing them back together seems fragile at best, here's an alternative that uses a powershell oneliner:

for /f %i in ('powershell -c "get-date -format yyyy-MM-dd--HH-mm-ss"') do @set DATETIME=%i
set LOGFILE=my-script-%DATETIME%.txt

Reference for get-date is here, with format options for both .NET-style and UNIX-style.

Here is a locale independent solution (copy to a file named SetDateTimeComponents.cmd):

@echo off
REM This script taken from the following URL:
REM http://www.winnetmag.com/windowsscripting/article/articleid/9177/windowsscripting_9177.html

REM Create the date and time elements.
for /f "tokens=1-7 delims=:/-, " %%i in ('echo exit^|cmd /q /k"prompt $d $t"') do (
   for /f "tokens=2-4 delims=/-,() skip=1" %%a in ('echo.^|date') do (
      set dow=%%i
      set %%a=%%j
      set %%b=%%k
      set %%c=%%l
      set hh=%%m
      set min=%%n
      set ss=%%o
   )
)

REM Let's see the result.
echo %dow% %yy%-%mm%-%dd% @ %hh%:%min%:%ss%

I put all my .cmd scripts into the same folder (%SCRIPTROOT%); any script that needs date/time values will call SetDateTimeComponents.cmd as in the following example:

setlocal

@echo Initializing...
set SCRIPTROOT=%~dp0
set ERRLOG=C:\Oopsies.err

:: Log start time
call "%SCRIPTROOT%\SetDateTimeComponents.cmd" >nul
@echo === %dow% %yy%-%mm%-%dd% @ %hh%:%min%:%ss% : Start === >> %ERRLOG%

:: Perform some long running action and log errors to ERRLOG.

:: Log end time
call "%SCRIPTROOT%\SetDateTimeComponents.cmd" >nul
@echo === %dow% %yy%-%mm%-%dd% @ %hh%:%min%:%ss% : End === >> %ERRLOG%

As the example shows, you can call SetDateTimeComponents.cmd whenever you need to update the date/time values. Hiding the time parsing script in it's own SetDateTimeComponents.cmd file is a nice way to hide the ugly details, and, more importantly, avoid typos.

Create a file with the current date as filename (ex. 2008-11-08.dat)

echo hello > %date%.dat    

With the current date but without the "-" (ex. 20081108.dat)

echo hello > %date:-=%.dat   

Maybe this can help:

echo off
@prompt set date=$d$_ set time=$t$h$h$h
echo some log >> %date% %time%.log
exit

or

echo off
set v=%date%.log
echo some log >> %v%

1) You can download GNU coreutils which comes with GNU date

2) you can use VBScript, which makes date manipulation easier in Windows:

Set objFS = CreateObject("Scripting.FileSystemObject")
strFolder = "c:\test"
Set objFolder = objFS.GetFolder(strFolder)
current = Now
mth = Month(current)
d = Day(current)
yr = Year(current)
If Len(mth) <2 Then
    mth="0"&mth
End If
If Len(d) < 2 Then
    d = "0"&d
End If
timestamp=yr & "-" & mth &"-"& d
For Each strFile In objFolder.Files
    strFileName = strFile.Name
    If InStr(strFileName,"file_name_here") > 0 Then
        BaseName = objFS.GetBaseName(strFileName)
        Extension = objFS.GetExtensionName(strFileName)
        NewName = BaseName & "-" & timestamp & "." & Extension
        strFile.Name = NewName
    End If
Next

Run the script as:

c:\test> cscript /nologo myscript.vbs

This works well with (my) German locale, should be possible to adjust it to your needs...

forfiles /p *PATH* /m *filepattern* /c "cmd /c ren @file 
%DATE:~6,4%%DATE:~3,2%%DATE:~0,2%_@file"

For big zip files for deployment, I use quarter hours. No one else on this page had mentioned it before, so I'll put my small script here:

set /a "quarter_hours=%time:~0,2%*4 + %time:~3,2% / 15"
set "zip_file=release_%DATE:~-4%.%DATE:~4,2%.%DATE:~7,2%.%quarter_hours%.zip"

It doesn't zero pad quarter hours from midnight to 5am yet, but it still makes it so you can have a stamped release multiple times a day with few collisions.

Hope that helps.

used Martin's suggestion with a little tweak to add time stamp to the file name:

forfiles /p [foldername] /m rsync2.log /c "cmd /c ren @file %DATE:~6,4%%DATE:~3,2%%DATE:~0,2%_%time:~-11,2%-%time:~-8,2%-%time:~-5,2%-@file

For the 10:17:21 23/10/2019 The result is:

20191023_10-17-21-rsync2.log

            echo Date and Time: %date% %time%
            rem 29/09/2021 10:01:34,23

            set timestamp=%time: =0%
            set timestamp=%timestamp::=%
            set timestamp=%timestamp:,=%
            set timestamp=%date:/=%%timestamp%

            echo Timestamp (ddMMYYYYHHmmssms): %timestamp%
            rem 2909202109543118

            set timestamp=%timestamp:~4,4%%timestamp:~2,2%%timestamp:~0,2%%timestamp:~8,8%
            echo Timestamp (YYYYMMddHHmmssms) %timestamp%
            rem 2021092910013423

Notice that you could be a little bit more flexible by using negative indexes... It will fit both English and West Europe date formats (of course with switched positions between days and months)

echo %DATE:~-10,2%%DATE:~-7,2%T%TIME:~0,2%%TIME:~3,2%

This is a 12 year old thread, but still active, and there has not yet been a truly locale-independent batch-only solution so here's my tuppence.

This should work on any windows setup, regardless of your local date settings. To be sure you get the correct DD MM and YYYY parts of the date you need to change the registry short-date format. Try this:

  • Store current registry short-date format in a local variable
  • Set the registry format to YYYYMMDD (or whatever you want)
  • Store current date to a local variable
  • Reset registry back to the original format

I keep the script below in 'YYYYMMDD.bat' and call it as needed.

@echo off 
:: Create environment variable containing current date in YYYYMMDD format.
:: Intended to be called from other batch jobs

::Save current registry date format
for /f "tokens=2*" %%a in ('reg query "HKCU\Control Panel\International" /v sShortDate^|find "REG_SZ"') do set "ssShortDate=%%b"

::Change registry date format to yyyymmdd 
reg add "HKCU\Control Panel\International" /f /v sShortDate /d "yyyyMMdd" >nul

::Save current date in yyyymmdd format 
set "YYYYMMDD=%date%"

::Restore original format to registry
reg add "HKCU\Control Panel\International" /f /v sShortDate /d "%ssShortDate%" >nul

echo YYYYMMDD=%YYYYMMDD%
timeout /t:1 >nul
exit /b
Related