Команда «dir» для Windows: сортировка файлов по дате, когда указано «/ s» - PullRequest
0 голосов
/ 19 декабря 2018

Цель: Я хочу скопировать последний файл с определенным расширением из «исходного каталога» в «целевой каталог», используя пакетный файл.Последний файл может находиться в нескольких подкаталогах внутри исходного каталога.

Этот вопрос / ответ - это именно то, что мне нужно, однако, похоже, он не сортируется, когда опция /sуказано (как этот комментарий будет предлагать ):

FOR /F "delims=|" %%I IN ('DIR "K:\path\tp\source\dir\*.ext" /B /S /O:D') DO SET NewestFile=%%I
copy "%NewestFile%" "C:\path\to\destination\dir"

Вы можете самостоятельно проверить DIR "K:\path\tp\source\dir\*.ext" /B /S /O:D, чтобы убедиться, что он не сортируется.

Что я пробовал: Эта команда сама по себе работает: DIR "K:\path\tp\source\dir\*.ext" /S /B | sort, но я не могу понять, как использовать ее в цикле for (пакетный файл завершается, прежде чем я могу определить ошибку - даже с pause в конце).

Есть идеи?

См .: dir docs

Ответы [ 3 ]

0 голосов
/ 19 декабря 2018

Вы можете вызвать Powershell из вашего пакетного файла, если хотите.Этот код можно сократить на более новых версиях Powershell.

for /F "delims=" %%G IN ('powershell "gci -rec | where { ! $_.PSIsContainer } | sort LastWriteTime | select -last 1 | Select-Object fullname"') do set NewestFile=%%G

Полный ответ:

cd /d "K:\path\to\source\dir"
for /F "delims=" %%G IN ('powershell "gci -rec *.ext | where { ! $_.PSIsContainer } | sort LastWriteTime | select -last 1 | Select-Object fullname"') do set NewestFile=%%G
copy "%NewestFile%" "C:\path\to\dest\dir"
0 голосов
/ 19 декабря 2018

Простое решение может быть

@echo off
    setlocal enableextensions disabledelayedexpansion

    set "root=K:\path\tp\source\dir"
    set "mask=*.ext"

    for %%r in ("%root%\.") do for /f "tokens=2,*" %%a in ('
        robocopy "%%~fr" "%%~fr" "%mask%" /njh /njs /nc /ns /ts /s /ndl /nocopy /is /r:0 /w:0 /l
        ^| sort /r 
        ^| cmd /v /e /c"(set /p .=&echo(!.!)"
    ') do set "lastFile=%%b"

    echo Last file : "%lastFile%"

Этот код использует robocopy для генерации списка файлов с префиксом временной метки (коммутаторы просто не запрашивают ни заголовка задания, ни сводки задания, ни класса файла,нет размера файла, метка времени, рекурсивно, нет списка каталогов, нет копии информации каталога, включаются те же файлы, нет повторов, нет ожидания, не копировать только генерировать список).

Этот список с префиксом времени (UTF yyyy/mm/dd hh:mm:ss последняя запись в файл) затем сортируется в обратном порядке, чтобы получить последний файл в первой строке.Эта строка извлекается с отдельным экземпляром cmd (это позволяет избежать проблем со временем при чтении длинных списков данных for /f), поэтому for /f читает только одну строку.

Поскольку строки robocopy содержат дату, время и имя файла, для извлечения этого последнего поля мы просим for /f извлечь два токена: один, содержащий час (будет храниться в %%a) и оставшийся текст до конца строки (сохраняется в %%b)

Дополнительный for %%r включен только для предотвращения обычной проблемы с использованием robocopy.Поскольку мы цитируем пути для предотвращения проблем с пробелами, мы должны убедиться, что пути не заканчиваются обратной косой чертой, которая будет экранировать закрывающую кавычку пути и приводить к сбою команды.

0 голосов
/ 19 декабря 2018

Кажется, все работает нормально.Я полагаю, что ваша проблема заключается в утверждении "delims=|" из вашей первоначальной функции.Используя "delims=", все, что нужно будет сделать, это отключить первый | от вывода циклов.Поскольку | не будет в обычном пути к файлу Windows, это совершенно не нужно.Попробуйте вместо этого просто ввести "tokens=*" в оператор.

Я также рекомендую использовать Set "String=" вместо традиционного Set String=, поскольку пробелы могут быть проблемой во многих случаях.Я обновил это в функции.

Пакетный скрипт:

@ECHO OFF

Rem | Configuration
Set "MainDirectory=C:\Folder1"
Set "FileExtension=*.txt"
Set "CopyDestination=C:\Folder2"

Rem | Search for the newest file in a directory/sub-directory
for /f "tokens=*" %%A in ('DIR "%MainDirectory%\%FileExtension%" /B /S /O:D') do (SET "NewestFile=%%A")

Rem | Copy file to a destination
copy "%NewestFile%" "%CopyDestination%"

goto :EOF
...