Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   Поиск самого свежего файла (http://forum.oszone.net/showthread.php?t=315232)

Flyer61rus 25-05-2016 23:21 2637668

Поиск самого свежего файла
 
Ребят, помогите написать bat файл, который бы искал самый свежие файл каждого расширения в указанной директории. То есть в папке Files находится много файлов разных расширений, например .doc, .excel, .txt и т.д. и таких файлов несколько. Так вот нужно найти самый свежий файл из .doc, .excel и так по всем расширениям. Вот бат файл, который ищет просто самый свежий файл, но как сделать, чтобы искал по каждому расширению не знаю. Если кто нибудь сделает, буду очень благодарен.

@echo off
for /f "delims=" %%i in ('dir C:\Files\ /B /A-D /OD /TA') do (set file=%%i)
echo %file%
pause

alpap 25-05-2016 23:45 2637670

Код:

@echo off
for %%a in (docx txt bat) do dir/a-d/b/o-d/tc "C:\Files\*.%%a"|set/p x=^&cmd/v/c echo !x!
pause>nul

.

Flyer61rus 25-05-2016 23:52 2637672

Цитата:

Цитата alpap
Код:
@echo off
for %%a in (docx txt bat) do dir/a-d/b/o-d/tc "C:\Files\*.%%a"|set/p x=^&cmd/v/c echo !x!
pause>nul »

Спасибо, но можно как нибудь сделать без указания конкретных расширений, чтобы учитывались все возможные расширения? Или такое в бат файле сделать невозможно?

alpap 26-05-2016 00:11 2637675

Flyer61rus,
Понимаете ли, если я укажу любое расширение, то это равносильно тому - найти единственный самый свежий файл, а если есть желание перечислить все известные расширения - пожалуйста, берите из архива ниже и продолжайте список в for.
Файл 137041

Flyer61rus 26-05-2016 00:41 2637676

Цитата:

Цитата alpap

В этом, собственно, и заключался вопрос, есть ли возможность указать в бат файле выборку по всем расширениям, не перечисляя каждое из возможных.

alpap 26-05-2016 03:20 2637685

Цитата:

Цитата Flyer61rus
есть ли возможность указать в бат файле выборку по всем расширениям, не перечисляя каждое из возможных. »

Есть - name.*, я же указал выше, но это автоматически любой файл и самый свежий один единственный, тоже написал об этом, как еще объяснить.

Iska 26-05-2016 05:05 2637689

Цитата:

Цитата Flyer61rus
самый свежий файл »

Переведите «самый свежий» — по дате создания, по дате последней модификации? По дате создания:
Скрытый текст
Код:

@echo off
setlocal enableextensions enabledelayedexpansion

set sSourceFolder=%~1

if defined sSourceFolder (
        for %%i in ("%sSourceFolder%\*.*") do set sFoundExt%%~xi=%%~xi
        for /f "usebackq tokens=2 delims==" %%i in (`set sFoundExt`) do for /f "usebackq delims=" %%j in (`2^>nul dir /b /a:-d /o:d /t:c "%sSourceFolder%\*%%~i"`) do set sFoundLastFileExt%%~i=%%j
        for /f "usebackq tokens=2 delims==" %%i in (`set sFoundLastFileExt`) do echo %%~i
) else (
        echo Usage: %~nx0 ^<Source folder^>
        exit /b 1
)

endlocal
exit /b 0


Путь к исходной папке указывается параметром пакетного файла.

Flyer61rus 26-05-2016 12:48 2637774

Цитата:

Цитата Iska
Переведите «самый свежий» — по дате создания, по дате последней модификации? По дате создания:
Скрытый текст »

Вот оно, то что нужно! Спасибо Вам большое, очень выручили! :yahoo:
Теперь только осталось самому посидеть поразбираться, что значат каждые параметры в этом коде) Еще раз большое Вам спасибо))

Iska 28-05-2016 08:31 2638229

Цитата:

Цитата Flyer61rus
Вот оно, то что нужно! »

Не совсем то. Я давно не писал и потому совершенно забыл, что ещё потребно проверять само существование папки, переданной параметром.

Цитата:

Цитата Flyer61rus
что значат каждые параметры в этом коде »

Если не разберётесь — спрашивайте.

Общий подход выглядит следующим образом:
  • получаем перечень всех файлов и создаём по их расширениям переменные окружения вида «sFoundExt<.Расширение>»;
  • следующим шагом производим разбор всех созданных переменных окружения вида «sFoundExt<.Расширение>», извлекая для каждой из них отсортированный по дате создания перечень файлов из той же папки, но уже с определённым расширением;
  • имя каждого подходящего файла присваивается одной и той же переменной окружения вида «sFoundLastFileExt<.Расширение>», таким образом, имя файла, созданного последним, будет присвоено этой переменной окружения последним, в самом конце перебора;
  • и, наконец, производим разбор всех созданных переменных окружения вида «sFoundLastFileExt<.Расширение>», извлекая присвоенное каждой из них найденное имя последнего файла определённого расширения.

Flyer61rus 05-06-2016 14:53 2640424

Цитата:

Цитата Iska
Если не разберётесь — спрашивайте. »

Добрый день, Iska! Извиняюсь, что спрашиваю уже спустя столько времени, но все же поясните пожалуйста как выполняется работа в этом коде. Мне бы буквально разобрать весь ход выполнения процесса в цикле. Можно даже на примере блок-схемы. :help: :help: :help:
Цитата:

Цитата Iska
if defined sSourceFolder (
for %%i in ("%sSourceFolder%\*.*") do set sFoundExt%%~xi=%%~xi »

Вот первый цикл. Объясните пожалуйста по шагам. Если я правильно понимаю, то если у нас существует папка, которую мы указываем через командную строку, то для всех файлов, находящихся в этой директории вводится новая переменная sFoundExt, которая... А вот что которая не понятно. Не могу разобраться что именно значит вот эта запись "sFoundExt%%~xi=%%~xi". Что за значение после равно? То что %~xi заменяет расширением имя файла %i понятно, но как это реализуется в данной строке? Почему написано через равно и почему %%, а не просто %?
Конечно, мои вопросы в некотором плане примитивны, но все же, если Вас не особо затруднит подробно рассказать о назначении и синтаксисе каждой переменной, буду очень благодарен.
Еще никак не могу разобраться с токенами. В нете почитал, но все же никак не пойму. Второй токен это значит, что в нашем случае будет выводиться %%~xi, так как находится после знака разделителя? Или что это значит?
Заранее большое спасибо Вам за ответ!

jenia_ov 23-12-2016 07:36 2697813

Ребята!
Подскажите пожалуйста, как в этом коде использовать найденный файл для копирования в другую директорию.
Код:

@echo off
setlocal enableextensions enabledelayedexpansion

set sSourceFolder=%~1

if defined sSourceFolder (
    for %%i in ("%sSourceFolder%\*.txt") do set sFoundExt%%~xi=%%~xi
    for /f "usebackq tokens=2 delims==" %%i in (`set sFoundExt`) do for /f "usebackq delims=" %%j in (`2^>nul dir /b /a:-d /o:d /t:c "%sSourceFolder%\*%%~i"`) do set sFoundLastFileExt%%~i=%%j
    for /f "usebackq tokens=2 delims==" %%i in (`set sFoundLastFileExt`) do echo %%~i
    for /f "usebackq tokens=3 delims==" %%i in (`set sFoundLastFileExt`) do copy %%~i d:\alfa.txt
) else (
    echo Usage: %~nx0 ^<Source folder^>
    exit /b 1
)
endlocal

exit /b

Поясню, требуется:
1) найти самый свежий файл с расширением txt в директории
2) скопировать найденный файл в другую директорию с переименованием в alfa.txt
3) если в директории назначения уже существует файл alfa.txt заменить его без подтверждения.

куда подставить txt для 1 пункта я понял, на 2 пункте сдулся, с 3 могу разобраться после того как узнаю имя/переменную в пункте 2.

Iska 23-12-2016 08:40 2697824

jenia_ov, не тот тэг используете. Надо [code], а не [spoiler].

Цитата:

Цитата jenia_ov
1) найти самый свежий файл с расширением txt в директории »

«Свежий» — по дате создания или по дате модификации?

Цитата:

Цитата jenia_ov
2) скопировать найденный файл в другую директорию с переименованием в alfa.txt »

Каким образом будет задаваться «другая директория»? Параметром или тупо в коде?

Цитата:

Цитата jenia_ov
как в этом коде использовать »

Никак. Вам нужен другой код.

Вот пример для а) по дате создания и б) папки задаются параметрами:
Скрытый текст
Код:

@echo off
setlocal enableextensions enabledelayedexpansion

set sSourceFolder=%~1
set sDestFolder=%~2

set sNewFileName=alfa.txt

if defined sSourceFolder (
        if defined sDestFolder (
                if exist "%sSourceFolder%\." (
                        if exist "%sDestFolder%\." (
                                for /f "usebackq delims=" %%i in (
                                        `2^>nul dir /b /a:-d /o:d /t:c "%sSourceFolder%\*.txt"`
                                ) do if not defined sFoundFile set sFoundFile=%%i
                               
                                if defined sFoundFile (
                                        >nul copy /y "%sSourceFolder%\!sFoundFile!" "%sDestFolder%\%sNewFileName%"
                                ) else (
                                        echo No txt files found.
                                        exit /b 4
                                )
                        ) else (
                                echo Can't find destination folder [%sDestFolder%].
                                exit /b 3
                        )
                ) else (
                        echo Can't find source folder [%sSourceFolder%].
                        exit /b 2
                )
        ) else (
                echo Usage: %~nx0 ^<Source folder^> ^<Destination folder^>
                exit /b 1
        )
) else (
        echo Usage: %~nx0 ^<Source folder^> ^<Destination folder^>
        exit /b 1
)

endlocal
exit /b 0


jenia_ov 23-12-2016 08:47 2697827

Iska, файл по дате создания, директории постоянные и неизменные, поэтому могу задаваться и в коде.
Ваш код полностью удовлетворяет потребности! Низкий Вам поклон!

Iska 23-12-2016 08:52 2697830

jenia_ov, хорошо. Тогда вместо использования аргументов просто укажите Ваши конкретные пути вместо выделенного:
Код:

set sSourceFolder=%~1
set sDestFolder=%~2


jenia_ov 23-12-2016 08:53 2697831

Iska, прошу прощения, сразу не обратил внимание, копируется самый старый файл почему-то.

Да, так и сделал, сначала кинулся ярлык сделал и пути прописал, потом только в код вписал каталоги.

Iska 23-12-2016 08:56 2697834

jenia_ov, попробуйте добавить «-» в «/o:d» в строку:
Код:

                                        `2^>nul dir /b /a:-d /o:d /t:c "%sSourceFolder%\*.txt"`
чтобы стало «/o:-d»:
Код:

                                        `2^>nul dir /b /a:-d /o:-d /t:c "%sSourceFolder%\*.txt"`

jenia_ov 23-12-2016 09:01 2697835

Iska, Огромное спасибо, все отлично!

Iska 23-12-2016 09:14 2697838

jenia_ov, ну, Вы таки попроверяйте всё ж. Может, окажется, что нужна была не дата создания…

jenia_ov 23-12-2016 09:32 2697845

Iska,
Суть процесса - с сайта клиент банка сохраняется выписка по счету в txt файле, поскольку работа идет из браузера chrome - он сохраняет эту выписку в папку Загрузки, как и все что скачивается через него. С помощью этого батника, самый свежий по дате создания txt файл копируется в расшаренную папку на сервере с 1С откуда и осуществляется загрузка этого файла. Выписка из банка всегда с разным именем файла (подставляется дата выписки). А поскольку txt файлы на том компе больше никто не качает, то это решение более чем подходит.

Vasya1998 16-08-2018 17:03 2826865

Цитата:

Цитата Iska
попробуйте добавить »

Помогите, пожалуйста, переписать батник таким образом, чтобы он находил последний созданный файл во вложенных папках. Я нашёл решение чтобы копировались все файлы из вложенных папок:
Код:

for /f "tokens=*" %%i in (' dir /b /s /ad "C:\SourceMainDir\" ') do xcopy /e "%%i" "C:\DestinationDir\"
но никак не получается соединить с кодом из этой темы так, чтобы из вложенных папок выбирался только самый последний созданный файл.

megaloman 16-08-2018 22:32 2826914

Vasya1998,
Если Дата/Время файла отображается в виде ДД.ММ.ГГГГ чч:мм, то вот вариант (поиск с точностью до минуты)
Код:

@Echo Off
cls
        Set "BoxIn=D:\CMD_Forum"
        Set "Mask=*.*"

        Set "NFname="
        Set "DTfile="
        Set  /A NFdate=0, NFtime=0
        For /F "usebackq delims=" %%j IN (`2^>nul Dir /A:-D /B /O:-D /T:W "%BoxIn%\%Mask%"`) DO (Call :NewFile "%BoxIn%\%%j" &GoTo :Cont)
        :Cont
        For /F "usebackq delims=" %%i IN (`2^>nul Dir /A:D /S /B /O:-D /T:W "%BoxIn%"`) DO Call :DirFiles "%%i" "%Mask%"

        Echo %DTfile% %NFname%
Pause
GoTo :Eof

:DirFiles
        For /F "usebackq delims=" %%j IN (`2^>nul Dir /A:-D /B /O:-D /T:W "%~1\%~2"`) DO (Call :NewFile "%~1\%%j" &GoTo :Eof)
GoTo :Eof

:NewFile
rem Echo %~t1 %1
        Set "Fdate=%~t1"
        Set /A Ftime=1%Fdate:~11,2%%Fdate:~14,2%
        Set /A Fdate=%Fdate:~6,4%%Fdate:~3,2%%Fdate:~0,2%
       
        If %Fdate% LSS %NFdate% GoTo :Eof
        If %Fdate% EQU %NFdate% If %Ftime% LSS %NFtime% GoTo :Eof

        Set /A NFdate=%Fdate%, NFtime=%Ftime%
        Set "NFname=%~1"
        Set "DTfile=%~t1"               
GoTo :Eof

В указанной папке с подпапками будет найден самый последний по времени изменения файл по указанной маске - Вы не уточняли, о каких файлах идёт речь, так что путь к папке и маску файлов напишите свои

YuS_2 17-08-2018 07:41 2826953

Цитата:

Цитата Vasya1998
переписать батник таким образом, чтобы он находил последний созданный файл во вложенных папках. »

Вот поправленный батник:
Код:

@echo off
set "src=C:\SourceMainDir"
set "dst=C:\DestinationDir"
for /f "delims=" %%i in ('powershell -ex bypass -c "&{(dir '%src%' -file -rec|sort -prop creationtime -desc).fullname[0]}"') do echo xcopy "%%i" "%dst%"
echo excellent!
pause&exit

в боевом применении, после do, команду echo следует удалить.

Iska 17-08-2018 08:11 2826956

YuS_2, фокус не удастся: файлы по дате, конечно, сортируются, но только в пределах того каталога, в котором находятся. То есть, таким образом мы получим самый свежий файл из… «корневого» для dir каталога (если в нём нет файлов — получим самый свежий файл из первого каталога, и там нет файлов — из первого вложенного в него, нет вложенных — из второго и т.д.). Это не массив объектов и не конвеер PowerShell, увы :).

YuS_2 17-08-2018 09:27 2826962

Цитата:

Цитата Iska
Это не массив объектов и не конвеер PowerShell, увы »

А, да, верно, совсем упустил из вида рекурсию! Это же cmd :)
При рекурсивном просмотре файлов, они же выводятся вместе с путями, при этом сначала сортируются по именам каталогов в пути, что бы там в ключах ни нарисовали... казалось бы, какого фига? Но увы, это ведь cmd... :)
Отсюда вывод: переходите на powershell, чтобы не было так мучительно больно... и тоскливо. :)
Поправил исходное решение...

Iska 17-08-2018 09:49 2826967

Цитата:

Цитата YuS_2
Отсюда вывод: переходите на powershell, чтобы не было так мучительно больно... и тоскливо. »

Таки да. Я не особо люблю PowerShell, но выбора, в общем-то, и нет.

YuS_2 17-08-2018 09:56 2826969

Цитата:

Цитата Iska
но выбора, в общем-то, и нет »

Ну, выбор-то есть всегда (cygwin, например, а в десятке так и вообще уже и cygwin не особо нужен)... вопрос в только в том, что предпочтительнее...

Iska 17-08-2018 10:06 2826972

Цитата:

Цитата YuS_2
cygwin, например, »

Чур меня, чур! ;).

Vasya1998 17-08-2018 10:41 2826988

Цитата:

Цитата megaloman
то вот вариант »

Спасибо, вам, большущее!
Оно работает. :)
Цитата:

Цитата YuS_2
поправленный батник »

Оно не заработало:
xcopy "Get-ChildItem : Не удается найти параметр, соответствующий имени параметра "file"." "C:\DestinationDir"
xcopy "строка:1 знак:32" "C:\DestinationDir"
xcopy "+ &{(dir 'C:\SourceMainDir' -file <<<< -rec|sort -prop creationtime -desc).fullname[0]}" "C:\DestinationDir"
xcopy " + CategoryInfo : InvalidArgument: (:) [Get-ChildItem], ParameterBindingException" "C:\DestinationDir"
xcopy " + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand" "C:\DestinationDir"
xcopy " " "C:\DestinationDir"
Но, в любом случае, большое спасибо.

А вообще, ребята, какие же вы красавчики, что помогаете. Спасибо вам всем за то что вы есть такие добрые.

YuS_2 17-08-2018 11:56 2827021

Цитата:

Цитата Vasya1998
Оно не заработало »

оно работает, если powershell обновить... :)
ну, а если случай запущенный (WinXP), то можно так:
Код:

@echo off
set "src=C:\SourceMainDir"
set "dst=C:\DestinationDir"
for /f "delims=" %%i in ('powershell -ex bypass -c "&{(dir '%src%' -rec|?{!$_.psiscontainer}|sort -prop creationtime -desc).fullname[0]}"') do echo xcopy "%%i" "%dst%"
echo excellent!
pause&exit

Но, кстати... если уж powershell на борту, то и всю задачу проще на него перевести...

Цитата:

Цитата Iska
Чур меня, чур! »

таладна, чего его бояться? :)
вполне функционально и достаточно производительно... ну, если уж powershell совсем не в радость...

Iska 17-08-2018 12:14 2827044

Цитата:

Цитата YuS_2
таладна, чего его бояться?
вполне функционально и достаточно производительно... ну, если уж powershell совсем не в радость... »

Ну, ежели токмо по анекдоту — «Слышь, Вась, по-моему и до аэродрома не так уж далеко» :lol:.

Vasya1998 17-08-2018 12:23 2827049

Цитата:

Цитата YuS_2
если powershell обновит »

У меня win7 и версия:
Major Minor Build Revision
----- ----- ----- --------
2 0 -1 -1

Но может быть, это связано с тем, что я запускал как cmd?
У меня с PowerShell вообще никак. Я так то админство много лет назад бросил, но вот случилось, что понадобилось, а я админил когда он только-только появился и всем хватало батников. :)

Iska 17-08-2018 12:39 2827060

Цитата:

Цитата Vasya1998
У меня win7 и версия:
Major Minor Build Revision
----- ----- ----- --------
2 0 -1 -1 »

На будущее можете обновить до пятой.


Цитата:

Цитата Vasya1998
когда он только-только появился и всем хватало батников. »

Не хватало. Причём категорически не хватало не только «батников», но и WSH, и KiXtart, и кучи Support Tools'ов и Resource Kit'ов.

YuS_2 17-08-2018 14:31 2827110

Цитата:

Цитата Vasya1998
Но может быть, это связано с тем, что я запускал как cmd? »

никак не связано, оно и написано в виде гибрида, т.е. для cmd
А в powershell 2.0, просто не поддерживается параметр -file у командлета Get-ChildItem, потому и не взлетело... обновите, как выше посоветовали, до версии 5.1, как минимум...


Время: 00:29.

Время: 00:29.
© OSzone.net 2001-