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


90

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

 yyyy-MM-dd.log

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

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

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

Получение строки даты с форматом, который вы хотите в файлах Windows .bat, выглядит так же плохо, как и предлагаемые решения. Честно говоря, просто проверьте, какие языки программирования доступны на машине, например java, ruby, perl или что-то еще, и сделайте 5-секундный исполняемый файл, чтобы дать вам то, что вы хотите. Я бы не стал тратить время на поддержку файла .bat, который требует более одной строки кода для получения даты в правильном формате.
99Sono,

Ответы:


106
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

6
Нужно было немного повозиться с индексами, но, похоже, это помогло. (хотя я не совсем уверен, что понимаю логику минус-индекса)% DATE: ~ -4% -% DATE: ~ -7, -5% -% DATE: ~ -10, -8% .log
Эоин Кэмпбелл,

1
Если вы хотите использовать все положительные индексы, вы можете использовать:% DATE: ~ 10,4% -% DATE: ~ 4,2% -% DATE: ~ 7,2%
opello

(Я просто взял это из чего-то еще, над чем работал, это было давно, и я понятия не имею, почему я сделал это так, как я делал изначально, хех.)
opello

3
Это не работает в других регионах. В моем случае команда возвращается 2014-5.-01(когда это будет 2014-05-26). Так что будьте очень осторожны, если вы публикуете скрипты, содержащие это!
amenthes

5
Используйте это для времени (убирает миллисекунды): %time:~-11,2%-%time:~-8,2%-%time:~-5,2%
MRC

48

Это сработало для меня и было безопасным для имени файла решением (хотя оно генерирует формат 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

Первая команда принимает ДАТУ и заменяет ее /на -, берет ВРЕМЯ, заменяет ее :на -и объединяет их в формат ДАТА @ ВРЕМЯ. Второй 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

вывод на моей консоли 10-12-2014@14-22-59,44.jpgс запятой перед миллисекундами
BeNdErR

1
Попробуйте добавить set SAVESTAMP=%SAVESTAMP:,=.%.jpgперед echoутверждением. Если это сработает, я обновлю ответ.
Daniel Sokolowski

1
Это не зависит от локали. Возврат 08.06.2016@15-42-20,33.jpgна моем немецком ноутбуке и Wed06-08-2016@15-43-45.89.jpgмоем английском.
Hannobo 08

5
Но он по-прежнему не является независимым от локали и не создает правильный (iso8601) форматyyyy-MM-dd
jeb

1
Досадно, что в первой строке все еще утверждается, что она не зависит от локали, просто чтобы убедиться, что это не так ...
m3tikn0b

16

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

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%

Превосходно! Немного сложно читать, но он позволяет форматировать вывод так, как вы хотите.
davitof

2
Отлично, но будьте осторожны, если хотите избежать белых символов, потому что ЧАС может быть 1 цифрой, представленной следующим образом: "_0:00"(символ подчеркивания - это пробел)
daVe

1
В ответ я получил "log- / 18 /. 0.Sa- 9.16.txt".
ledlogic

@ledlogic: какой у вас регион? Это ответ для французского языка.
Aubin

1
НЕ работает Я получаю это в Windows 7 - log- / 05 /. 0.We-18.13.tx
Sam B

10

Вот независимое от локали решение (скопируйте в файл с именем 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 - хороший способ скрыть некрасивые детали и, что более важно, избежать опечаток.


2
извините, это не зависит от локали: в моей французской Windows я получаю «18-2014- @ 13:14:43»
davitof

1
Могу подтвердить: не зависит от локали. prompt $d $tвозвращает 30.05.2016 15: 35: 56,93 в моей системе.
Hannobo 08

7

Поскольку идея разорвать %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-стиле.


6

Я часто использую это и помещаю все в одну команду копирования. Следующий файл 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"

6

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

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

:: ------------------ 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%

2

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

echo hello > %date%.dat    

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

echo hello > %date:-=%.dat   

2

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

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%

Хороший, Секко ... у этого значения% date%, похоже, есть то, что я ищу. Если есть шанс, вы можете объяснить инструкцию SET. Что такое $ d $ _set и $ t $ h $ h $ h
Эоин Кэмпбелл,

1
set - это оператор "SET переменной". Где переменная даты - $ d $ _ (день + остаток), а переменная времени - $ t $ h $ h $ h (время + мс). Я попытался показать, как это можно сделать с набором переменных, он может нормально работать без строки подсказки. Я в основном пытался сделать это set date =% YYYY %% MM %% DD%, но я запускаю здесь Linux и компилирую скрипт на SciTE, поэтому я не знаю, работает ли он. Извините, если это не сработает.
Secko,

Забыл добавить, $ _ - это новая строка.
Secko,

1
Также попробуйте, @prompt // $ d $ _ $ t $ h $ h $ h $ h $ h $ h //
Секко,

Обратите внимание, что это также не зависит от локали. Дата отформатирована в соответствии с текущими настройками культуры, в моем случае ДД.ММ.ГГГГ (для немецкого).
Hannobo 08

2

Я собрал небольшую программу на 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


2

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

@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%

Это было полезно для меня, хотя в файле ".cmd" двоеточие в переменной "FreshTime" вызывало ошибки при использовании для имени файла в моей командной строке "robocopy": ERROR : Invalid Parameter #12 : "/LOG:C:\opt\Sync_08.10.2020_16:27:39.log"В качестве исправления вместо этого я использовал тире:set FreshTime=%hour%-%min%-%secs%
netdesignate

2

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

::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

2

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

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

1

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

0

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

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

%DATE:~6,4%%DATE:~3,2%%DATE:~0,2%работает и для португальского местоположения! Я имею в виду ГГГГММДД
Фернандо Фабрети

0

Для развертывания больших 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 утра, но все же делает так, чтобы вы могли выпускать штампы несколько раз в день с небольшими столкновениями.

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


0

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.