Как добавить отметку времени в строки журнала в файле журнала из вывода пакетного файла?

Я хочу добавить отметку времени в строки журнала из пакетного вывода.

Вот мой командный файл:

@Echo off
SET LOGFILE=MyLogFile.log
call :Logit >> %LOGFILE% 
exit /b 0

:Logit
set "affix=%date%_%time%"
set "affix=%affix::=%"
set "affix=%affix:/=%"
xcopy "I:\DF\AB\Data.xlsx" "D:\TL\BACKUP\Data_%affix%.xlsx"*

Вывод файла журнала:

I:\DF\AB\Data.xlsx
1 File(s) copied

Я хочу, чтобы выходной файл журнала выглядел так:

I:\DF\AB\Data.xlsx
20180831_124500 : 1 File(s) copied

Как это могло быть достигнуто?

Еще немного информации:

  1. Звездочка в конце строки целевого аргумента необходима для копирования файла без запроса. Если * не будет использоваться в конце имени целевого файла, появится приглашение с вопросом, является ли цель файлом или каталогом.
  2. xcopy используется, потому что копируется файл с сетевого диска на локальный диск.

Результат вывода после запуска командного файла выглядит следующим образом:

I:\DF\AB\Data.xlsx
08312018_163959.07 :I:\DF\AB\Data.xlsx
1 File(s) copied

Может быть, как показано ниже?

I:\DF\AB\Data.xlsx
08312018_163959.07  1 File(s) copied 

Таким образом, формат даты, зависящий от региона, — MM/DD/YYY, а формат времени — HH:mm:ss.ms.


person v1787v    schedule 31.08.2018    source источник
comment
прямо под самой последней строкой поместите эту строку echo %affix%, которая все равно установит все, как вы хотели, скопируйте файл, но просто при вызове метки она будет отображать время и дату изменения в файле журнала после копирования файла.   -  person Gerhard    schedule 31.08.2018


Ответы (4)


Вы только XCopy создаете один файл, поэтому знаете, что последней строкой вывода в случае успеха будет строка, зависящая от языка, 1 File(s) copied.
Поскольку вы уже ограничили скрипт использованием зависящих от локали %DATE% и %TIME%, я предположил, что языковая зависимость для этой задачи в порядке.

Поэтому вот смехотворно выглядящий пример скрипта:

@Echo Off
Set "srcfile=I:\DF\AB\Data.xlsx"
Set "destdir=D:\TL\BACKUP"
Set "logfile=MyLogFile.log"

For %%A In ("%srcfile%") Do Set "dstname=%%~nA" & Set "destext=%%~xA"

For /F "Tokens=1-2 Delims=|" %%A In ('
    Echo F^|XCopy "%srcfile%" "|%DATE:/=%_%TIME::=%|" /L 2^>Nul ^&^
    Echo F^|Xcopy "%srcfile%" "%destdir%\%dstname%_%DATE:/=%_%TIME::=%%destext%" /Y ^>Nul 2^>^&1
') Do (If Not "%%B"=="" Set "_=%%B"
    If Defined _ If /I "%%A"=="%srcfile%" ((
            Echo %%A&Call Echo %%_%%  1 File(s^) copied)>"%logfile%"))

Вы не должны изменять ничего, кроме значений переменных в строках 2-4.
Однако если вы используете существующий файл журнала, вы можете замените > в последней строке на >>

person Compo    schedule 31.08.2018

Вы можете использовать echo| set /p=%affix% для устранения новой строки во время эха:

@Echo off
SET LOGFILE=MyLogFile.log
call :Logit >> %LOGFILE% 
exit /b 0
:Logit
set "affix=%date%_%time%"
set "affix=%affix::=%"
set "affix=%affix:/=%"
echo|set /p=%affix% :
xcopy "I:\DF\AB\Data.xlsx" "D:\TL\BACKUP\Data_%affix%.xlsx"*

Результат:

I:\DF\AB\Data.xlsx
2018-08-31_124900 :        1 file(s) copied.
person Gerhard    schedule 31.08.2018
comment
@v1787v. Это лучшее, что я могу сделать, я удалил файловое эхо, так как это был тест, но ваш результат не может отличаться от этого, вы не можете разделить вывод команды по умолчанию, единственным возможным способом было бы создать цикл for , направьте команду в nul, затем используйте вывод и разделите его на переменную и эхо в файл. но это кажется действительно ненужным. - person Gerhard; 31.08.2018

powershell -command "(New-TimeSpan -Start (Get-Date "01/01/1970") -End (Get- Date)).TotalSeconds">LOG.TXT

Хотя это не тот формат, который вы предложили, этот формат называется epoch time.
Преимущество этого формата в том, что это всегда значение с плавающей запятой.

LOG.TXT будет именем журнала, убедитесь, что вы находитесь в правильном каталоге.

person Benjamin2002    schedule 04.09.2018
comment
Большое спасибо Benjamin2002 - person v1787v; 06.09.2018

Я предлагаю следующий код, производящий именно тот исходный вывод в файле журнала:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "LOGFILE=MyLogFile.log"
del "%LOGFILE%" 2>nul
call :Logit >>"%LOGFILE%"
endlocal
exit /B 0

:Logit
set "FileDate=%DATE:~-4%%DATE:~-10,2%%DATE:~-7,2%_%TIME:~0,2%%TIME:~3,2%%TIME:~6,2%"
for /F "tokens=1* delims=:" %%I in ('%SystemRoot%\System32\xcopy.exe "I:\DF\AB\Data.xlsx" "D:\TL\BACKUP\Data_%FileDate%.xlsx*" /C /V /Y 2^>nul') do (
    if not "%%J" == "" (
        echo %%I:%%J
    ) else (
        echo %FileDate% : %%I
    )
)
goto :EOF

Дата и время, зависящие от региона, переформатируются в yyyyMMdd_HHmmss с помощью замены строк динамических переменных среды DATE и TIME, как подробно объясняется, например, в ответе на вопрос: Что означает %date:~-4,4%%date:~-10,2%%date:~-7,2%_%time:~0,2%%time:~3,2 % означает? Для гораздо более медленного, но независимого от региона решения, чтобы получить дату/время в определенном формате, см., например, ответ на: Почему %date% дает другой результат в пакетном файле, выполняемом как запланированное задание?

Текущая дата и время в формате yyyyMMdd_HHmmss присваиваются переменной среды FileDate, используемой дважды в следующей строке, один раз в имени целевого файла и еще раз в выводе последней строки переформатированного вывода команды XCOPY.

Например, здесь используется командная строка XCOPY:

C:\Windows\System32\xcopy.exe "I:\DF\AB\Data.xlsx" "D:\TL\BACKUP\Data_20180831_163959.xlsx*" /C /R /V /Y 2>nul

Эта командная строка выполняется FOR в отдельном командном процессе, запущенном FOR с cmd.exe /C в фоновом режиме. FOR захватывает все строки, записанные для обработки STDOUT этого командного процесса, перед обработкой захваченных строк.

XCOPY выводит для обработки STDOUT имена скопированных файлов с полным путем и в последней строке сводную информацию. Ошибки при копировании файлов записываются в обработчик STDERR, которые подавляются путем перенаправления их на устройство NUL.

Прочтите также статью Microsoft о Использование операторов перенаправления команд для объяснения 2>nul. Оператор перенаправления > должен быть экранирован символом вставки ^ в командной строке FOR, чтобы он интерпретировался как буквальный символ, когда интерпретатор команд Windows обрабатывает эту командную строку перед выполнением команды FOR, которая выполняет встроенная командная строка xcopy в отдельный командный процесс, запущенный в фоновом режиме.

Звездочка * в конце имени целевого файла должна быть в двойных кавычках второй строки аргумента, а не снаружи, потому что в противном случае cmd.exe соответственно xcopy.exe должен исправить этот неправильный синтаксис.

Обратите внимание, что трюк с * в конце имени целевого файла работает здесь случайно, потому что исходный и целевой файлы имеют одинаковое расширение, а имя исходного файла всегда короче, чем имя целевого файла. В противном случае команда завершится ошибкой или целевой файл получит нежелательное имя, являющееся конкатенацией имени целевого файла + символов имени исходного файла после n символов имени целевого файла.

Как правило, есть лучшие способы избежать остановки при запросе, который запрашивает XCOPY в случае, если один файл копируется с новым именем файла. Письмо для ответа на приглашение может быть выведено сначала в STDOUT, перенаправленное для обработки STDIN команды XCOPY, как продемонстрировано независимо от языка в ответе на пакетный файл запрашивает файл или папку.

Захваченные выходные данные XCOPY обрабатываются FOR построчно с пропуском пустых строк и строк, начинающихся с точки с запятой ;, поскольку это символ конца строки по умолчанию для опции eol= не используется. здесь.

Цель здесь состоит в том, чтобы вывести все строки с полным файлом, выводимым с помощью XCOPY в фоновом командном процессе, а также в этом командном процессе, но вывести последнюю строку с другой сводной информацией, добавив перед ней дату/ время в желаемом формате, пробел, двоеточие и еще один пробел.

По этой причине поведение разделения строк по умолчанию для пробелов/табуляций с присвоением только первой подстроки (токена) указанной переменной цикла I изменено здесь параметрами tokens=1* delims=:. FOR теперь разделяет строку двоеточиями.

Только строки с полным именем файла, начинающимся с буквы диска и двоеточия, вообще содержат двоеточие. В таких строках буква диска назначается указанной переменной цикла I, как указано tokens=1. Остальная часть строки имени файла после первого двоеточия назначается без дальнейшего разделения следующей переменной цикла в соответствии с таблицей ASCII зациклить переменную J, которая находится здесь после двоеточия после буквы диска.

Строка сводной информации не содержит двоеточия. По этой причине FOR присваивает всю сводную информацию переменной цикла I, а J содержит пустую строку.

Переменная цикла J никогда не бывает пустой в строке с именем файла, начинающимся с буквы диска и двоеточия. Этот факт используется здесь, чтобы определить, следует ли выводить строку из XCOPY как есть со вставкой удаленного двоеточия между буквой диска и путем к файлу + именем файла + расширением файла или выводить сводную информацию с датой/временем. в начале.

Обратите внимание, что этот метод работает только при копировании файлов с диска с буквой диска. Другой метод потребуется для исходных файлов с путем UNC.

На самом деле копирование одного файла может быть выполнено намного проще с помощью команды COPY вместо XCOPY, даже с/на сетевой диск или когда имя исходного/целевого файла указано с UNC дорожка. COPY также имеет параметры /V и /Y и даже /Z, например XCOPY. COPY не создает целевую структуру каталогов, как XCOPY, но это можно сделать с помощью команды MD ранее. COPY не может перезаписать файл только для чтения, как это может сделать XCOPY при использовании параметра /R, но это ограничение COPY, скорее всего, не имеет значения. здесь. И COPY не копирует файл с установленным скрытым атрибутом. Однако, как правило, копирование одного файла лучше всего выполнять с помощью команды COPY вместо XCOPY.

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

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "LOGFILE=MyLogFile.log"
md "D:\TL\BACKUP" 2>nul
del "%LOGFILE%" 2>nul
call :Logit >>"%LOGFILE%"
endlocal
exit /B 0

:Logit
set "FileDate=%DATE:~-4%%DATE:~-10,2%%DATE:~-7,2%_%TIME:~0,2%%TIME:~3,2%%TIME:~6,2%"
echo I:\DF\AB\Data.xlsx
copy /B /V /Y "I:\DF\AB\Data.xlsx" "D:\TL\BACKUP\Data_%FileDate%.xlsx" >nul 2>nul && echo %FileDate% : 1 File(s) copied|| echo %FileDate% : 0 File(s) copied
goto :EOF

Преимущество этого решения также в том, что вывод строки в случае успеха или ошибки можно полностью настроить. COPY завершает работу со значением больше 0 при ошибке, такой как исходный файл недоступен или целевой файл/каталог защищен от записи в настоящее время или постоянно.

Пример лучшего вывода для одного скопированного файла в случае успеха или ошибки (только подпрограмма):

:Logit
set "FileDate=%DATE:~-4%%DATE:~-10,2%%DATE:~-7,2%_%TIME:~0,2%%TIME:~3,2%%TIME:~6,2%"
copy /B /V /Y "I:\DF\AB\Data.xlsx" "D:\TL\BACKUP\Data_%FileDate%.xlsx" >nul 2>nul
if not errorlevel 1 (
    echo %FileDate% : Copied successfully I:\DF\AB\Data.xlsx
) else (
    echo %FileDate% : Failed to copy file I:\DF\AB\Data.xlsx
)
goto :EOF

Конечно, также можно использовать командную строку

set "FileDate=%DATE:/=%_%TIME::=%"

в командном файле, чтобы получить дату и время в формате MMddyyyy_HHmmss.ms, если это действительно нужно сейчас. Я не рекомендую этот формат даты/времени, так как он плохо подходит для алфавитного списка всех Data_*.xlsx файлов в каталоге D:\TL\BACKUP. Список файлов, отсортированных по имени, с форматом даты/времени yyyyMMdd_HHmmss автоматически также отсортирован по дате/времени.

Чтобы понять, какие команды используются и как они работают, откройте окно командной строки, выполните в нем следующие команды и внимательно прочитайте все страницы справки, отображаемые для каждой команды.

  • call /?
  • copy /?
  • del /?
  • echo /?
  • endlocal /?
  • exit /?
  • for /?
  • goto /?
  • if /?
  • md /?
  • set /?
  • setlocal /?
  • xcopy /?

Смотрите также:

person Mofi    schedule 31.08.2018
comment
Большое спасибо Мофи - person v1787v; 06.09.2018