Дата и время пакетной команды в имени файла
Я сжимаю файлы, используя 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%.