Показать полную графическую версию : Как из папки выбрать в переменную уникальные имена файлов
Banzaika
22-07-2010, 21:48
День добрый,
подскажите, запутался,
есть каталог, в нем файлы типа:
2010.07.21-xx_ab.zip
2010.06.14-xxx.zip
2010.08.21-xx_ab.zip
2010.09.14-xxx.zip
2010.07.11-xx_ab.zip
2010.06.04-xxx.zip
2010.08.26-xx_ab.zip
2010.02.14-xxx.zip
Мне нужна переменная в которой только уникальные имена, т.е. например x=xx_ab xxx
Затык в том, что у меня получается цикл в цикле:
1. бежать в каталоге по именам файлов
2. если в нашей переменной такое имя не встречалось, то set переменная=%переменная% %имя_текущего_файла%
в этом случае второй цикл не хочет просматривать переменную и тем более "на ходу" ее дополнять
@echo off
SetLocal EnableExtensions
SetLocal EnableDelayedExpansion
set idfile=
for /f "tokens=1* delims=-" %%i in ('dir *.zip /b') do (
for /f "delims= " %%x in (!idfile!) do (
if not %%x == %%j set idfile=!idfile! %%j
)
)
@echo idfile=%idfile%
хотя если собрать все имена файлов в каталоге в 1 переменную, то работает
@echo off
SetLocal EnableExtensions
SetLocal EnableDelayedExpansion
set idfile=
for /f "tokens=1* delims=-" %%i in ('dir *.zip /b') do (
set idfile=!idfile! %%j
)
echo idfile=%idfile%
но мне нужны в переменной только уникальные имена! иначе дальнейшую обработку не могу организовать...
Уточните проблему более подробными примерами - ничего не понятно.
Banzaika
23-07-2010, 21:21
Уточняю:
каждый день на сервере появляются файлы бэкапа в виде zip-архивов.
Эти файлы ВСЕ в имени сначала имеют дату создания, затем уникальное имя - то с чего сделан бэкап.
Этого "то с чего сделан бэкап" у меня около 12 штук.
Вопрос: в каталоге может быть несколько тысяч файлов, но мне нужно знать именно их уникальные имена, то есть с чего это бэкапы.
Пример:
2010.07.21-xx_ab.zip, где
2010.07.21 - дата
xx_ab - уникальное имя
Более того, я уже даже решил проблему, но по извращенному:
for /f "tokens=1* delims=-" %%i in ('dir *.zip /b') do (echo. > %%j.id)
Эта строка пробегает по именам всех zip в каталоге и отбрасывая первую часть с датой, создает пустой файлик с расширением *.id.
В конечном итоге по этим файликам я точно знаю какие именно бэкапы в каталоге и могу уже использовать их имена для задания маски для дальнейшей обработки.
(мне нужно каждого типа бэкапов хранить всего 5 последних штук, т.е. с сервера-1 5 последних, сервера-2 5 последних и т.д)
Хочу услышать критику и возможно решение через find.
Может кто-то покажет красивее?
Не 1й раз пишу на этом форуме, и хочу предупредить, я хочу решение ИМЕННО в виде bat, на худой конец vbs.
Не предлагайте варианты стороннего ПО, все должно работать "из коробки".
P.S. Почему не обрабатывается переменная цикла в цикле??
Не помню таких ограничений.
т.е. например for %%i do (for %%x do ...) - как обойти ограничение что %х игнорируется??
Не понимаю я
SetLocal EnableExtensions
SetLocal EnableDelayedExpansion
или вернее для передачи переменной в цикл надо ее брать в !переменная!
а как взять в "!" переменную %%i?
Понимаю вопрос задал криво, но вот как есть
могу предложить первым циклом забросить имена в файл:
for /f "tokens=1* delims=-" %%i in ('dir *.zip /b') do (
echo %%J >> 1.tmp
)
далее сортируем и идем перебором:
for /f "delims= " %%x in ('sort 1.tmp') do (
if '!last1!' NEQ '%%x' set idfile=!idfile! %%x
set last1=%%x
)
echo !idfile!
у себя проверил - работает.
ps: лучше взять временное имя файла и в конце удалить его.
El Sanchez
24-07-2010, 13:59
мне нужно каждого типа бэкапов хранить всего 5 последних штук, т.е. с сервера-1 5 последних, сервера-2 5 последних и т.д »
Значит все остальное удаляем:
@Echo Off
SetLocal EnableDelayedExpansion
Set Source=C:\Source
Set NumSavedFiles=5
Set Count=1
Echo.>_UniqueNames.log
For /F "Tokens=1* Delims=-" %%A In ('Dir /B "%Source%\*.zip"') Do (
Find "%%B" _UniqueNames.log 1>nul 2>&1||Echo %%B>>_UniqueNames.log&&Call :Func "!Count!"
)
Del /F /Q _UniqueNames.log 1>nul 2>&1
EndLocal
GoTo :EOF
:Func
For /F "Skip=%~1 Tokens=*" %%C In ('Type _UniqueNames.log') Do (
For /F "Skip=%NumSavedFiles% Tokens=*" %%D In ('Dir /B /O-D /TC "%Source%\*%%C"') Do Del /F /Q "%Source%\%%D" 1>nul 2>&1
)
Set /A Count+=1
Banzaika
24-07-2010, 15:44
QRS
В цикле сортировки, если верить подсказке на команду if то операторы сравнения (neq - не равно) допустимо использывать при "расширенной обработке команд"... Точно ли не нужен ключ "/i"???
И не совсем понял сколько раз нужно делать цикл? Ведь будут исключены лишь явно повторяющиеся значения последовательности, например 1123112 превратится в 12312. Мне то на выхлопе нужно получить просто 123...
Может я что-то не правильно понял про команду sort? (фокус с созданием файлов в том что при выполнении цикла они др др заменяют, но в итоге остаются лишь "уникальные")
El Sanchez
Круто, только можно прокомментировать строки? Если честно не все понимаю... хотя и вижу сценарии не 1й раз...
El Sanchez
24-07-2010, 19:45
Banzaika,
Echo.>_UniqueNames.log »
Пишем пустую строку в файл _UniqueNames.log, где будет список уникальных имен.
For /F "Tokens=1* Delims=-" %%A In ('Dir /B "%Source%\*.zip"') Do (
Find "%%B" _UniqueNames.log 1>nul 2>&1||Echo %%B>>_UniqueNames.log&&Call :Func "!Count!"
) »
Основной цикл. Из вывода команды Dir берем из каждой строки все, что после дефиса, т.е. уникальное имя (переменная %B). Ищем имя в файле _UniqueNames.log (Find "%%B" _UniqueNames.log 1>nul 2>&1) и, если в файле его еще нет (||), то записываем его (Echo %%B>>_UniqueNames.log). Если запись произведена (&&), то вызываем процедуру Func с передаваемым в нее параметром Count - количество строк для пропуска.
Сама процедура:
:Func
For /F "Skip=%~1 Tokens=*" %%C In ('Type _UniqueNames.log') Do (
For /F "Skip=%NumSavedFiles% Tokens=*" %%D In ('Dir /B /O-D /TC "%Source%\*%%C"') Do Del /F /Q "%Source%\%%D" 1>nul 2>&1
)
Set /A Count+=1 »
, где For /F "Skip=%~1 Tokens=*" %%C In ('Type _UniqueNames.log') - печатаем наш лог-файл и пропускаем количество строк, заданное в ключевом слове Skip. %~1 - это
наше количество строк Count, переданное из основного цикла. Skip не может начинаться с нуля, по-этому в самом начале и записана пустая строка в _UniqueNames.log.
В %С попадет последняя строка, содержащая уникальное имя.
For /F "Skip=%NumSavedFiles% Tokens=*" %%D In ('Dir /B /O-D /TC "%Source%\*%%C"') Do Del /F /Q "%Source%\%%D" 1>nul 2>&1 - сортируем все файлы, содержащие в себе уникальное имя %C,
начиная с самого нового (/O-D /TC), пропускаем нужные 5 файлов (%NumSavedFiles%), а все остальное удаляем.
Set /A Count+=1 - увеличиваем количество строк, т.к. при следующем найденном уникальном имени нужно будет пропускать в _UniqueNames.log на строку больше.
El Sanchez
25-07-2010, 11:38
Banzaika,
Вариант №2, попроще и покороче, но время выполнения дольше:
@Echo Off
Set Source=C:\Source
Set NumSavedFiles=5
For /F "Tokens=1* Delims=-" %%A In ('Dir /B "%Source%\*.zip"') Do (
For /F "Skip=%NumSavedFiles% Tokens=*" %%C In ('Dir /B /O-D /TC "%Source%\*%%B"') Do Del /F /Q "%Source%\%%C"
)
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.