Я предлагаю следующий код, производящий именно тот исходный вывод в файле журнала:
@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
echo %affix%
, которая все равно установит все, как вы хотели, скопируйте файл, но просто при вызове метки она будет отображать время и дату изменения в файле журнала после копирования файла. - person Gerhard   schedule 31.08.2018