Создание имени файла в качестве метки времени в пакетном задании

У нас есть пакетное задание, которое выполняется каждый день и копирует файл в папку раскладки. Я также хочу взять копию этого файла и поместить ее в архив с именем файла

 yyyy-MM-dd.log

Какой самый простой способ сделать это в пакетном задании Windows?

Я в основном ищу эквивалент этой команды Unix:

cp source.log `date +%F`.log

20 ответов

Решение
CP source.log %DATE:~-4%-%DATE:~4,2%-%DATE:~7,2%.log

Но это зависит от локали. Я не уверен, если %DATE% локализован или зависит от формата, указанного для краткой даты в Windows.

Вот независимый от локали способ извлечь текущую дату из этого ответа, но это зависит от WMIC а также 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

Это сработало для меня и было безопасным для имени файла решением (хотя оно генерирует формат MM-dd-YYYY):

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

Первая команда принимает DATE и заменяет / с -, берет ВРЕМЯ и заменяет : с -и объединяет их в формат DATE @ TIME. Второй set оператор удаляет любые пробелы, а третий set заменяет , с . и добавляет .jpg расширение.

Приведенный выше код используется в небольшом скрипте, который извлекает изображения с IP-камеры безопасности для дальнейшей обработки:

: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

Только для французского языка (Франция), будьте осторожны, потому что / появляется в дате:

echo %DATE%
08/09/2013

Для нашей проблемы файла журнала вот мое предложение ТОЛЬКО для французской локали:

SETLOCAL
set LOGFILE_DATE=%DATE:~6,4%.%DATE:~3,2%.%DATE:~0,2%
set LOGFILE_TIME=%TIME:~0,2%.%TIME:~3,2%
set LOGFILE=log-%LOGFILE_DATE%-%LOGFILE_TIME%.txt
rem log-2014.05.19-22.18.txt
command > %LOGFILE%

Потому что идея рвать %DATE% а также %TIME% кроме того, и объединение их друг с другом кажется в лучшем случае хрупким, вот альтернатива, которая использует оболочку powershell:

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

Ссылка для get-date здесь, с параметрами формата для.NET-стиля и UNIX-стиля.

Вот независимое от локали решение (скопируйте в файл с именем 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%

Я помещаю все свои сценарии.cmd в одну папку (%SCRIPTROOT%); любой скрипт, которому нужны значения даты / времени, будет вызывать SetDateTimeComponents.cmd, как в следующем примере:

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%

Как показывает пример, вы можете вызывать SetDateTimeComponents.cmd всякий раз, когда вам нужно обновить значения даты / времени. Скрытие скрипта разбора времени в своем собственном файле SetDateTimeComponents.cmd - хороший способ скрыть неприятные детали и, что более важно, избежать опечаток.

Я часто использую это и помещаю все в одну команду копирования. Следующий пример копирует example.txt как example_YYYYMMDD_HHMMSS.txt и, конечно, вы можете изменить его в соответствии с вашим предпочтительным форматом. Кавычки необходимы только в том случае, если в спецификации файла есть пробелы. Если вы хотите повторно использовать одну и ту же метку даты / времени, вам необходимо сохранить ее в переменной.

copy "{path}\example.txt" "{path}\_%date:~10,4%%date:~4,2%%date:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%.txt"

Это гарантирует, что выходной сигнал будет состоять из 2 цифр... вы можете изменить выходной сигнал по своему вкусу и протестировать его, не комментируя раздел диагностики. Наслаждайтесь!

(Я позаимствовал это на других форумах...)

:: ------------------ Date and Time Modifier ------------------------

@echo off
setlocal

:: THIS CODE WILL DISPLAY A 2-DIGIT TIMESTAMP FOR USE IN APPENDING FILENAMES

:: CREATE VARIABLE %TIMESTAMP%

for /f "tokens=1-8 delims=.:/-, " %%i in ('echo exit^|cmd /q /k"prompt $D $T"') do (
   for /f "tokens=2-4 skip=1 delims=/-,()" %%a in ('echo.^|date') do (
set dow=%%i
set %%a=%%j
set %%b=%%k
set %%c=%%l
set hh=%%m
set min=%%n
set sec=%%o
set hsec=%%p
)
)

:: ensure that hour is always 2 digits

if %hh%==0 set hh=00
if %hh%==1 set hh=01
if %hh%==2 set hh=02
if %hh%==3 set hh=03
if %hh%==4 set hh=04
if %hh%==5 set hh=05
if %hh%==6 set hh=06
if %hh%==7 set hh=07
if %hh%==8 set hh=08
if %hh%==9 set hh=09


:: --------- TIME STAMP DIAGNOSTICS -------------------------

:: Un-comment these lines to test output

:: echo dayOfWeek = %dow%
:: echo year = %yy%
:: echo month = %mm%
:: echo day = %dd%
:: echo hour = %hh%
:: echo minute = %min%
:: echo second = %sec%
:: echo hundredthsSecond = %hsec%
:: echo.
:: echo Hello! 
:: echo Today is %dow%, %mm%/%dd%. 
:: echo.
:: echo. 
:: echo.
:: echo.
:: pause

:: --------- END TIME STAMP DIAGNOSTICS ----------------------

:: assign timeStamp:
:: Add the date and time parameters as necessary - " yy-mm-dd-dow-min-sec-hsec "

endlocal & set timeStamp=%yy%%mm%%dd%_%hh%-%min%-%sec%
echo %timeStamp%

Создайте файл с текущей датой в качестве имени файла (напр. 2008-11-08.dat)

echo hello > %date%.dat    

С текущей датой, но без "-" (напр. 20081108.dat)

echo hello > %date:-=%.dat   

Вы можете просто определить текущий локальный формат и получить дату в вашем формате, например:

::for 30.10.2016 dd.MM.yyyy
if %date:~2,1%==. set d=%date:~-4%%date:~3,2%%date:~,2%
::for 10/30/2016 MM/dd/yyyy
if %date:~2,1%==/ set d=%date:~-4%%date:~,2%%date:~3,2%
::for 2016-10-30 yyyy-MM-dd
if %date:~4,1%==- set d=%date:~,4%%date:~5,2%%date:~-2%
::variable %d% have now value: 2016103 (yyyyMMdd)
set t=%time::=%
set t=%t:,=%
::variable %t% have now time without delimiters
cp source.log %d%_%t%.log

Может быть, это может помочь:

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

или же

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

Я знаю, что эта ветка старая, но я просто хочу добавить это сюда, потому что она мне очень помогла, пытаясь понять все это и его чистоту. Приятно то, что вы можете поместить его в цикл для пакетного файла, который всегда работает. Журнал работы сервера или что-то в этом роде. Это то, что я использую это для в любом случае. Я надеюсь, что это поможет кому-нибудь когда-нибудь.

@setlocal enableextensions enabledelayedexpansion
@echo off

call :timestamp freshtime freshdate
echo %freshdate% - %freshtime% - Some data >> "%freshdate - Somelog.log"

:timestamp
set hour=%time:~0,2%
if "%hour:~0,1%" == " " set hour=0%hour:~1,1%
set min=%time:~3,2%
if "%min:~0,1%" == " " set min=0%min:~1,1%
set secs=%time:~6,2%
if "%secs:~0,1%" == " " set secs=0%secs:~1,1%
set FreshTime=%hour%:%min%:%secs%

set year=%date:~-4%
set month=%date:~4,2%
if "%month:~0,1%" == " " set month=0%month:~1,1%
set day=%date:~7,2%
if "%day:~0,1%" == " " set day=0%day:~1,1%
set FreshDate=%month%.%day%.%year%

Я знаю, что это старый пост, но есть более простой ответ FAR (хотя, возможно, он работает только в более новых версиях Windows). Просто используйте параметр /t для команд DOS и TIME, чтобы только показывать дату или время, а не предлагать их установить, например так:

@echo off
echo Starting test batch file > testlog.txt
date /t >> testlog.txt
time /t >> testlog.txt

Я собрал небольшую программу на C, чтобы распечатать текущую временную метку (безопасный для локали, без плохих символов...). Затем я использую команду FOR, чтобы сохранить результат в переменной среды:

:: Get the timestamp
for /f %%x in ('@timestamp') do set TIMESTAMP=%%x

:: Use it to generate a filename
for /r %%x in (.\processed\*) do move "%%~x" ".\archived\%%~nx-%TIMESTAMP%%%~xx"

Вот ссылка:

https://github.com/HarryPehkonen/dos-timestamp

1) Вы можете скачать GNU coreutils, который поставляется с датой GNU

2) вы можете использовать VBScript, который облегчает манипулирование датами в 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

Запустите скрипт как:

c:\test> cscript /nologo myscript.vbs

Для больших zip-файлов для развертывания я использую четверть часа. Никто на этой странице не упоминал об этом раньше, поэтому я выложу здесь свой небольшой сценарий:

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"

Он не обнуляет четверти часа с полуночи до 5 утра, но все же делает это так, что вы можете получить штампованный релиз несколько раз в день с небольшим количеством столкновений.

Надеюсь, это поможет.

Этому потоку уже 12 лет, но он все еще активен, и еще не было по-настоящему независимого от локали пакетного решения, так что вот мой tuppence.

Это должно работать при любой настройке Windows, независимо от ваших локальных настроек даты. Чтобы убедиться, что вы получаете правильные части даты DD MM и YYYY, вам нужно изменить формат краткой даты реестра. Попробуй это:

  • Сохранить текущий формат короткой даты реестра в локальной переменной
  • Установите формат реестра ГГГГММДД (или любой другой)
  • Сохранить текущую дату в локальной переменной
  • Сбросить реестр в исходный формат

Я храню приведенный ниже сценарий в «ГГГГММДД.bat» и вызываю его по мере необходимости.

      @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

Это хорошо работает с (моим) немецким языком, должно быть возможно приспособить его к вашим потребностям...

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

Использовал предложение Мартина с небольшой настройкой, чтобы добавить отметку времени к имени файла:

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

За 10:17:21 23.10.2019 Результат такой:

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

Обратите внимание, что вы могли бы быть немного более гибким, используя отрицательные индексы... Он будет соответствовать формату даты как английского, так и западноевропейского (конечно, с переключением позиций между днями и месяцами).

эхо %ДАТА:~-10,2%%ДАТА:~-7,2%Т%ВРЕМЯ:~0,2%%ВРЕМЯ:~3,2%

Другие вопросы по тегам