Дата и время пакетной команды в имени файла

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

Для генерации имени файла я использую следующее. Скопируйте его в свою командную строку и вы увидите имя файла с компонентом Дата и время.

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

Выход

Archive_20111011_ 93609.zip

Однако моя проблема - AM vs PM. Временная метка AM дает мне время 9 (с ведущим пробелом) и 10, естественно занимая два пробела.

Я предполагаю, что моя проблема будет распространяться на первые девять дней, первые 9 месяцев и т.д. Также.

Как исправить это, чтобы вместо нужных пробелов были включены ведущие нули, поэтому я получаю Archive_20111011_093609.zip?

Ответ 1

Другое решение:

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

Он даст вам (независимо от настроек локали!):

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

Отсюда легко:

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

Для запроса Logan для одного и того же выходного формата для "модифицированного по дате" файла:

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%

Это немного сложнее, потому что он работает только с полными путями, wmic ожидает, что обратная косая черта будет удвоена, а = должен быть экранирован (первый, второй защищен окружающими кавычками).

Ответ 2

Извлеките час, найдите ведущее пространство, если его замените нулем;

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

Ответ 3

Вы должны искать; вы можете просто заменить все пробелы нулем set hr=%hr: =0% - jeb 11 октября 11 в 14:16

Итак, я сделал:

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

Затем используйте %hr% внутри любой строки, которую вы форматируете, чтобы всегда получать двузначный час.

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

Ответ 4

Как уже указывал Вики, %DATE% и %TIME% возвращают текущую дату и время, используя короткие форматы даты и времени, которые можно полностью (бесконечно) настраивать.

Один пользователь может настроить свою систему на возврат Fri040811 08.03PM, а другой пользователь может выбрать 08/04/2011 20:30.

Это полный кошмар для программиста BAT.

Изменение формата в твердый формат может устранить проблему, если вы вернете предыдущий формат перед выходом из BAT файла. Но он может быть подвержен неприятным условиям гонки и усложнять восстановление в отмененных файлах BAT.

К счастью, есть альтернатива.

Вместо этого вы можете использовать WMIC. WMIC Path Win32_LocalTime Get Day,Hour,Minute,Month,Second,Year /Format:table возвращает дату и время неизменным образом. Очень удобно непосредственно проанализировать его командой FOR /F.

Итак, соединяя кусочки, попробуйте это как отправную точку...

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
 )

Ответ 5

Я нашел лучшее решение для меня, прочитав все ваши ответы:

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

Если AM я получаю 20160915_ 150101 (с ведущим пространством и временем).

Если PM я получаю 20160915_2150101.

Ответ 6

Вы можете добавить ведущие нули в переменную (значение до 99), подобное этому в пакете: IF 1%Var% LSS 100 SET Var=0%Var%

Итак, вам нужно проанализировать свои компоненты даты и времени на отдельные переменные, обрабатывать их все так, а затем объединить их вместе, чтобы создать имя файла.

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

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

(Этот последний контролирует, есть ли ведущий ноль по времени, но не даты, насколько я знаю).

Ответ 7

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

Это займет MB5L.txt и сжимает его до ziptest20120204.zip, если он запущен 4 февраля 2012 г.

Ответ 8

Из вышеприведенного ответа я сделал готовую к использованию функцию.

Проверено с французскими локальными настройками.

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

Ответ 9

Ваш вопрос, кажется, решен, но...

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

Это возможно с помощью ZIP и 1980, это было хорошим решением, но сегодня вы должны использовать систему репозитория, такую ​​как subversion или git или..., но не zip файл.

Хорошо, возможно, может быть, я ошибаюсь.

Ответ 10

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

Загрузите gawk для Windows в http://gnuwin32.sourceforge.net/packages/gawk.htm.... Тогда это один лайнер, без всякого неуклюжего синтаксиса DOS, где требуется шесть циклов FOR для разделения строк (WTF? Это действительно НАДЕЖНО МАД И САД!... ИМХО, конечно)

Если вы уже знаете C, С++, Perl или Ruby, то собираете AWK (который наследуется от первых двух, и вносит значительный вклад в последние два) является частью пресловутой ТОРТЫ!!!

Команда DOS Batch:

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

Печать

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

Теперь, когда не совсем полная история... Я просто буду лениться и жестко закодировать остальную часть моего имени файла журнала в заявлении printf, потому что это просто... Но если кто-нибудь знает, как для установки переменной% NOW% в AWK-выход (выстраивая кишки "общей" функции теперь), тогда я все уши.


EDIT:

Быстрый поиск в Stack Overflow, заполненный этой последней частью головоломки, Пакетный эквивалент Bash backticks.

Итак, эти три строки партии DOS:

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

Итак, теперь я могу включить datetime в имя файла журнала, созданного моей установкой сервера SQL Server (2005+) script, таким образом:

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

И я снова счастливый турист (кроме жизни все еще SOOOOO намного проще в Unix).

Ответ 11

Большинство из этих решений требуют вызова даты и времени отдельно, а некоторые из них делают несколько вызовов для каждого. Если команда запускается так же, как часы переворачиваются, эти вызовы будут возвращать разные значения. Например, если Date вызывается незадолго до полуночи, а Time вызывается сразу после полуночи, результат будет отображаться как сразу после полуночи даты вызова Date. Аналогично, если Time вызывается до полуночи, а Date вызывается после полуночи, результат будет перед полночью новой даты. Хотя вероятность этого невелика, это НЕ невозможно. Единственное правильное решение, которое предотвращает это, - это то, которое считывает часы только один раз и возвращает дату и время вместе. Из всех представленных здесь решений единственными, которые удовлетворяют этому требованию, являются те, которые называют wmic.

Если у вас есть лучший способ прочитать дату и время вместе, пожалуйста, напишите!

Ответ 12

Как уже отмечали другие, форматы даты и времени %DATE% и %TIME% (а также date/T и time/T) зависят от локали, поэтому извлечение текущей даты и времени всегда является кошмаром, и невозможно получить решение, которое работает со всеми возможными форматами, поскольку практически нет ограничений по формату.


Но есть другая проблема с кодом, подобным следующему (предположим, что формат даты, например, MM/DD/YYYY и 12-часовой формат времени, например, h:mm:ss ap где ap - это AM или PM):

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%

Каждый экземпляр %DATE% и %TIME% возвращает значение даты или времени, присутствующее во время его расширения, поэтому первое выражение %DATE% или %TIME% может возвращать значение, отличное от следующих (вы можете доказать, что когда отображение длинной строки, содержащей огромное количество таких, предпочтительно %TIME%, выражений).

Вы могли бы улучшить вышеупомянутый код для хранения одного экземпляра %DATE% и %TIME% следующим образом:

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%

Но, тем не менее, возвращаемые значения в %DATE% и %TIME% могут отражать разные дни при выполнении в полдень.

Единственный способ получить один и тот же день в %CURRDATE% и %CURRTIME% - это:

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%

Конечно, возникновение описанной проблемы весьма маловероятно, но в один прекрасный момент это произойдет и вызовет странные необъяснимые сбои.


Описанная проблема не может возникнуть с подходами, основанными на команде wmic как описано в ответе пользователя Стефана и в ответе пользователя PA. , поэтому я настоятельно рекомендую пойти на один из них. Единственный недостаток wmic том, что он намного медленнее.

Ответ 13

В именах файлов допустимо пробел. Если вы укажете свой путь и имя файла в кавычках, он может просто летать. Вот что я использую в пакетном файле:

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

Не имеет значения, есть ли пробелы в% filename%.