Найти последний созданный файл в каталогах и подкаталогах с помощью PowerShell или Windows Batch - PullRequest
0 голосов
/ 01 апреля 2020

У меня есть 30 различных папок, через которые нужно перебирать, в каждой есть папка Log и внутри нее текстовые файлы. Я за последним, который мне нужно скопировать в новое местоположение с предпочтительным именем (EG 2020-03-28.txt.FolderServerName1 , где добавленная переменная FolderServerName1, определяет, с какого сервера он пришел from)

set source="\\ServerName\LogFolders" 
set target=" C:\Data\CopiedLogFiles"
FolderServerName1
    Log
        2020-03-26.txt
        2020-03-27.txt
        **2020-03-28.txt**
FolderServerName2
    Log
        2020-03-26.txt
        2020-03-27.txt
        **2020-03-28.txt**
FolderServerName3
    Log
        2020-03-26.txt
        2020-03-27.txt
        **2020-03-28.txt**

https://devblogs.microsoft.com/oldnewthing/20120801-00/?p=6993

Пост выше очень полезен, но я думаю, что мне нужен еще один вложенный l oop, в котором Я борюсь с синтаксически.

Большое спасибо!

1 Ответ

0 голосов
/ 02 апреля 2020

Эту задачу копирования файлов можно выполнить с помощью:

@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 /?
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...