Показать полную графическую версию : [решено] Скопировать из множества папок по одному самому новому файлу с переименованием.
NuclearBox
12-09-2021, 00:47
Здравствуйте.
Задача - собрать (скопировать по маске) из множества папок по одному последнему созданному в них файлу в целевую папку. И при копировании присвоить этим файлам имена исходных папок.
Хотелось это сделать через присвоение множества папок одной переменной, поскольку папки могут быть в разных местах и на разную глубину:
set "F01=D:\FOLDER1"
set "F02=D:\FOLDER2"
set "F03=D:\FOLDER3"
set FSET="%F01%" "%F02%" "%F03%"
, чтобы использовать потом в конструкции
FOR /D %%d IN (%FSET%) DO
Для копирования последних созданных файлов нашел на форуме код уважаемого megaloman
http://forum.oszone.net/thread-224061.html
Но связать все это вместе не смог.
Прошу помочь. Или подскажите альтернативное решение.
Serguei Kouzmine
12-09-2021, 01:53
@NuclearBox это можно связать вместе костыльным методом показанном ниже
но не рекомендую....займтитесь лучще изучением повершела
может сначала надо определяться задачей, а уже потом выбирать костыли для ее решения
пример
@echo OFF
setlocal enableextensions enabledelayedexpansion
set LIST=X
set LIST=!LIST! Y
set LIST=!LIST! Z
echo LIST=!LIST!
:LOOP
FOR /F "tokens=1,* delims= " %%a in ('echo !LIST!') do (
SET TOKEN=%%a
set LIST=%%b
call :PROCESS !TOKEN!
if "!LIST!" neq "" GOTO :LOOP
)
goto :EOF
:PROCESS
ECHO processing %1
goto :EOF
получаем
a.cmd
LIST=X Y Z
processing X
processing Y
processing Z
@echo off
set "d1=C:\Program Files\Internet Explorer"
set "d2=C:\Program Files\7-Zip\Lang"
set "d3=D:\Video\Разное\Животные"
set "out=C:\OUT"
for %%d in ("%d1%" "%d2%" "%d3%") do (
pushd "%%d"
for /f "delims=" %%f in ('"dir /a-d/b/o-d/tc|set /p name=^& call echo %%name%%"') do call :#_copy "%%f" "%%d"
popd
)
pause& exit
:#_copy
if not exist "%out%" md "%out%"
copy "%~1" "%out%\%~nx2%~x1"
exit /b
но вот есть такая бяка:
при копировании присвоить этим файлам имена исходных папок »
я это выполнил в коде, но предупредить надо. Если будет следующее копирование, файлы затрутся новыми - имена-то одни и те же получаться, может при переименовании делать двойные имена: "Папканоситель_староеимяфайла.ext"?
NuclearBox
12-09-2021, 03:11
Serguei Kouzmine, спасибо за ответ и совет. Код попробую применить, ценно по умолчанию. Советом пока не воспользуюсь, дефицит времени. Ищу именно cmd- или bat-решение.
alpap, спасибо большое, Ваши конструкции больше понимаю и учусь на них.
Останется добавить отбор файлов по маске, думаю с этим справлюсь.
Но по именам Вы правы - файлы затрутся не только при следующем копировании (в моем случае не страшно), но как понимаю и при текущем, если у их папок на диске одинаковое имя. Например,
set "d1=C:\Program Files\Internet Explorer"
set "d2=C:\Program Files\7-Zip\Lang"
set "d3=D:\Video\Разное\Животные\Lang"Добавление "староеимяфайла.ext" не спасет, если попадутся файлы и с одинаковыми именами. Есть ли способ добавить не старое имя файла, а имя переменной папки (d1, d2, d3), или порядковый номер, который соответствует их очередности в коде?
…если у их папок на диске одинаковое имя »
Добавление "староеимяфайла.ext" не спасет, если попадутся файлы и с одинаковыми именами. »
Именно так.
Если Вы расскажете, что это за файлы, почему они находятся в разных каталогах, с какой именно целью Вы их собираете в одном месте — возможно, Вам подскажут и:
альтернативное решение. »
Возможно, даже и не требующее их сбора в одном каталоге :).
или порядковый номер »
@echo off
set "d1=C:\Program Files\Internet Explorer"
set "d2=C:\Program Files\7-Zip\Lang"
set "d3=D:\Video\Разное\Животные"
set "out=C:\OUT"
for %%d in ("%d1%" "%d2%" "%d3%") do (
set /a n+=1
pushd "%%d"
for /f "delims=" %%f in ('"dir /a-d/b/o-d/tc|set /p name=^& call echo %%name%%"') do call :#_copy "%%~f" "%%~d" "%%n%%"
popd
)
pause& exit
:#_copy
if not exist "%out%" md "%out%"
>nul copy "%~1" "%out%\%~nx2_%~3%~x1"
exit /b
добавить отбор файлов по маске »
тогда теряется вся прелесть кода, он берет именно последний созданный и теперь будет писать что не найдет если нет.
маску ставить: ...dir /a-d/b/o-d/tc "сюда" ... и тогда стоит записать так с учетом вышенаписанного: ... 2>nul dir /a-d/b/o-d/tc "сюда" ...
NuclearBox
12-09-2021, 04:55
Iska, это файлы, которые периодически формируют программы и специалисты, и которые долго отслеживать, собирать и обрабатывать вручную. Общий каталог нужен для автоматического формирования итоговых файлов на их основе. Просто автоматизация ежедневной работы.
alpap, Роскошно! Это именно то, что нужно. Супер-Пупер код! Работает идеально. "Сюда" - тоже).
Еще один полигон для изучения. Огромное спасибо!
megaloman
12-09-2021, 10:36
Общий каталог нужен для автоматического формирования итоговых файлов на их основе. Просто автоматизация ежедневной работы. »
При такой постановке будете сегодня делать итоговый файл имея в наличии самые разные по времени создания файлы. Прошлогодние файлы тоже годятся?папки могут быть в разных местах и на разную глубину: »А какое их общее количество? Что, заранее их список неизвестен и они могут появляться/исчезать непредсказуемым для вас образом? Не получится ли так, что одинаковые по смыслу и источнику поступления данные имеются в соседних папках, которые созданы кем-то для сортировки, например, по времени? Хотелось бы проникнуться смыслом задачи.
NuclearBox
12-09-2021, 14:50
megaloman, здравствуйте.
Вероятность получить "древний" документ исключена. Устаревшие на заданную глубину дней документы в этих папках сначала переместятся в подпапки old ( http://forum.oszone.net/thread-349519.html ), следующему процессу они будут не видны.
Общее количество собираемых файлов менее 30. Какие-то формируются строго ежедневно, какие-то без четкой периодичности, по мере готовности.
Известны папки обновления, характер данных, форматы файлов. Для большинства известна структура наполнения. Имена файлов и количество - не подлежат систематизации из-за особенностей программ (как присваиваются имена) и личных предпочтений специалистов (когда и как обновляются - перезаписью или накапливанием, какие названия и т.д.).
Совпадение файлов по смыслу и источнику исключено, "смыслы" не пересекаются. Это не новостной сборщик, хотя можно, наверное, с доработкой применять батник и для таких задач.
Из собранных файлов постранично формируется несколько профильных файлов + общий документ, автоматизация с помощью конвертеров и Pdftk.
megaloman
12-09-2021, 21:33
Всегда с интересом рассматриваю оригинальное творчество alpap, ИМХО необходимо перед копированием очищать Out.
Немного другой вариант: я не нумерую все файлы, я нумерую файлы только с совпадающими именами, а не сплошняком. Нумерация файлов с одинаковыми именами и разными расширениями из одной папки одинаковая. Учитываю маски.@Echo Off
cls
Set Folders="Z:\Program Files\Internet Explorer" "Z:\Program Files\7-Zip\Lang" "Z:\Video\Разное\Животные" "Z:\Box_In\Program Files\Internet Explorer" "Z:\Box_In\Program Files\7-Zip\Lang" "Z:\Box_In\Video\Разное\Животные"
Set Mask="*.bat" "2*.xlsx"
Set "Out=Z:\Out"
2>nul Pushd "%Out%" &&(2>nul Rd "%Out%" /S /Q &Popd)||(>nul 2>&1 Md "%Out%")
For %%d In (%Folders%) Do Call :MyCopy "%%~d" "%%~nxd" "%Mask%" "%Out%"
For /F "usebackq delims=" %%d In (`2^>nul Dir %Folders% /B /S /A:D`) Do Call :MyCopy "%%d" "%%~nxd" "%Mask%" "%Out%"
pause
Exit /B
:MyCopy
Pushd %1
Set "Add="
If Not Exist "%~4\%~2.*" GoTo :ContMyCopy
Set /A i=100
:Begin
Set /A i+=1
Set "Add=_%i:~-2%"
If Exist "%~4\%~2%Add%.*" GoTo :Begin
:ContMyCopy
Call :MyReCopy %4 %2 "%Add%" %~3
Popd
Exit /B
:MyReCopy
If "%~4"=="" Exit /B
For /F "usebackq delims=" %%f In (`2^>nul Dir %4 /B /A:-D /O:-D /T:W`) Do (>nul Copy "%%f" "%~1\%~2%~3%%~xf" &GoTo :ContMyReCopy)
:ContMyReCopy
Shift /4
GoTo :MyReCopy
Exit /B
NuclearBox
12-09-2021, 22:54
megaloman, большое спасибо. Это как раз то решение, на которое я замахнулся и не осилил.
Не так лаконично, как предложил alpap, но для меня очень ценно, чтобы понимать, как использовать множества папок и масок через общую переменную.
Параметр /s для обхода подпапок исключу, в моем случае он лишний.
По нумерации - вариант, но для визуального контроля удобнее вариант alpap - зная код, можно быстро определить какой файл с повторяющимся именем из какой папки пришел, или не пришел.
С советом предварительно очищать OUT соглашусь и учту.
Очень благодарен.
Еще раз спасибо всем за помощь.
megaloman
12-09-2021, 23:04
Параметр /s для обхода подпапок исключу, в моем случае он лишний. »Уберите красный For и больше ничего не изменяйте.
NuclearBox
12-09-2021, 23:52
megaloman, Точно, спасибо.
megaloman
13-09-2021, 00:02
зная код, можно быстро определить какой файл с повторяющимся именем из какой папки пришел, или не пришел »@Echo Off
cls
Set Folders="Z:\Program Files\Internet Explorer" "Z:\Program Files\7-Zip\Lang" "Z:\Video\Разное\Животные" "Z:\Box_In\Program Files\Internet Explorer" "Z:\Box_In\Program Files\7-Zip\Lang" "Z:\Box_In\Video\Разное\Животные"
Set Mask="*.bat" "2*.xlsx"
Set "Out=Z:\Out"
Set "Log=Z:\Out\__%~nx0.log"
2>nul Pushd "%Out%" &&(2>nul Rd "%Out%" /S /Q &Popd)||(>nul 2>&1 Md "%Out%")
For %%d In (%Folders%) Do Call :MyCopy "%%~d" "%%~nxd" "%Mask%" "%Out%"
rem For /F "usebackq delims=" %%d In (`2^>nul Dir %Folders% /B /S /A:D`) Do Call :MyCopy "%%d" "%%~nxd" "%Mask%" "%Out%"
pause
Exit /B
:MyCopy
Pushd %1
Set "Add="
If Not Exist "%~4\%~2.*" GoTo :ContMyCopy
Set /A i=100
:Begin
Set /A i+=1
Set "Add=_%i:~-2%"
If Exist "%~4\%~2%Add%.*" GoTo :Begin
:ContMyCopy
Call :MyReCopy %1 %4 %2 "%Add%" %~3
Popd
Exit /B
:MyReCopy
If "%~5"=="" Exit /B
For /F "usebackq delims=" %%f In (`2^>nul Dir %5 /B /A:-D /O:-D /T:W`) Do (
>nul Copy "%%f" "%~2\%~3%~4%%~xf"
>>"%Log%" Echo "%~2\%~3%~4%%~xf" ^<---- "%~1\%%f"
GoTo :ContMyReCopy
)
:ContMyReCopy
Shift /5
GoTo :MyReCopy
Exit /B
NuclearBox
13-09-2021, 00:38
megaloman, Да, логично, не подумал об этом. Круто и даже избыточно.
А теперь задача со звёздочкой: если там а) и впрямь копирование, б) в пределах одного раздела, в) в скопированные файлы не вносится изменений — вместо копирования создаём жёсткие ссылки :).
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.