Эту задачу копирования файлов можно выполнить с помощью:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /D %%I in ("\\ServerName\LogFolders\*") do (
set "CopyDone="
for /F "delims=" %%J in ('dir "%%I\Log\20??-??-??.txt" /A-D-H /B /O-N 2^>nul') do if not defined CopyDone (
copy /Y "%%I\Log\%%J" "C:\Data\CopiedLogFiles\%%~nJ_%%~nxI%%~xJ" >nul
set "CopyDone=1"
)
)
endlocal
Для каждого не скрытого подкаталога в \\ServerName\LogFolders
внешний FOR l oop сначала удаляет переменную среды CopyDone
и запускает еще один FOR l oop.
Внутренний FOR l oop запускается в фоновом режиме еще одним командным процессом с использованием %ComSpec% /c
и командная строка заключена в '
в качестве дополнительных команд. Выполнение с Windows, установленным в C:\Windows
, например, в фоновом режиме:
C:\Windows\System32\cmd.exe /c dir "\\ServerName\LogFolders\FolderServerName1\Log\20??-??-??.txt" /A-D /B /O-N 2>nul
Команда DIR выполняет поиск в указанном каталоге
- только для не скрытые файлы из-за опции
/A-D-H
(атрибут не каталог и не скрытый) - с именем файла, совпадающим с шаблоном подстановки
20??-??-??.txt
- , и выводит в голом формате из-за опции
/B
только каждое имя файла с расширением без пути - упорядочено в обратном порядке по имени из-за опции
/O-N
- для обработки STDOUT (стандартный вывод) процесса фоновой команды .
Обратный вывод, отсортированный в алфавитном порядке по именам, приводит к именам файлов журнала, которые 2020-03-28.txt
выводятся в первой строке, 2020-03-27.txt
во второй строке и 2020-03-26.txt
в третьей строке.
Возможно, подкаталог Log
вообще не существует или не содержит файла, соответствующего шаблону подстановочного знака. В этом случае команда DIR выводит сообщение об ошибке для обработки STDERR (стандартная ошибка), которое подавляется путем перенаправления его на устройство NUL с помощью 2>nul
.
Прочтите статью Microsoft о Использование операторов перенаправления команд для объяснения 2>nul
. Оператор перенаправления >
должен быть экранирован с помощью символа вставки ^
в FOR командной строке, чтобы интерпретироваться как литеральный символ, когда интерпретатор команд Windows обрабатывает эту командную строку перед выполнением команды FOR который выполняет встроенную dir
командную строку в отдельном командном процессе, запущенном в фоновом режиме.
Командный процесс, обрабатывающий пакетный файл, захватывает все, что записано для обработки STDOUT фонового командного процесса и FOR обрабатывает этот захваченный вывод построчно после запуска cmd.exe
завершается сам.
FOR игнорирует пустые строки, которые здесь не встречаются.
FOR будет по умолчанию разделять каждую строку на подстроки с использованием обычного пробела и символа горизонтальной табуляции в качестве разделителей строк, и будет выглядеть следующим образом, если первая подстрока начинается с символа конца строки по умолчанию ;
, в этом случае строка также будет игнорируется и в противном случае назначил бы только первый пробел / табуляцию ограниченная строка указанной переменной l oop. Здесь было бы возможно использовать это поведение обработки строки по умолчанию, поскольку имена файлов не содержат пробела. Но, тем не менее, лучше отключить режим разделения строк, используя delims=
для определения пустого списка разделителей строк.
Таким образом, внутренний FOR назначает на первой итерации l oop файл имя самого нового файла в соответствии с международной форматированной датой в имени файла для l oop переменная J
и запускает команду IF .
на первой l oop итерации внутренней FOR l oop переменная окружения CopyDone
всегда не определена, как указано выше в командной строке, поэтому условие IF выполняется.
Для этого причина, по которой файл копируется, что означает для первой папки FolderServerName1
, что выполненная команда COPY :
copy /Y "\\ServerName\LogFolders\FolderServerName1\Log\2020-03-28.txt" "C:\Data\CopiedLogFiles\2020-03-28_FolderServerName1.txt" >nul
Имя целевого файла изменено с запрошенного 2020-03-28.txt.FolderServerName1
на 2020-03-28_FolderServerName1.txt
, Как правило, лучше использовать точку в имени файла только один раз в качестве разделителя между именем файла и расширением файла и держать расширение файла в конце имени файла, чтобы иметь возможность открывать файл двойным щелчком мыши.
Переменная среды CopyDone
определяется со значением после того, как копирование файла выполнено без проверки на успешность. Строковое значение, присвоенное переменной среды CopyDone
, в этом случае не имеет значения.
Внутреннее FOR продолжает обрабатывать захваченные строки, присваивая одно имя файла за другим l oop переменная J
и выполнение условия IF . Но это условие не выполняется ни для какого другого имени файла, кроме первого имени файла.
Чтобы понять используемые команды и их работу, откройте окно командной строки и выполните там следующие команды и внимательно прочитайте все справочные страницы, отображаемые для каждой команды.
copy /?
dir /?
echo /?
endlocal /?
for /?
if /?
set /?
setlocal /?