Как добавить метку времени к строкам журнала в файле журнала из выходных данных пакетного файла? - PullRequest
0 голосов
/ 31 августа 2018

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

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

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

Ответы [ 4 ]

0 голосов
/ 04 сентября 2018

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

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

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

0 голосов
/ 31 августа 2018

Вы только 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.
Однако вы должны использовать существующий файл журнала Вы можете изменить > в последней строке на >>

0 голосов
/ 01 сентября 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 %% дата: ~ -10,2 %% дата: ~ -7,2% _% время: ~ 0,2 %% время: ~ 3,2% значит? Для гораздо медленнее, но Решение, не зависящее от региона, для получения даты / времени в определенном формате, см., например, ответ на % date% дает другой результат в пакетном файле при запуске из запланированных задач на сервере 2016 .

Текущие дата и время в формате 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 /?

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

0 голосов
/ 31 августа 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.
...