![]() |
Архивирование файлов определенного типа из подкаталогов
Добрый день.
Прошу помощи с написанием скрипта для решения такой задачи: Вводные Имеем множество папок, в каждой из которых есть файлы с различными расширениями и размерами соответственно.
Необходимо создать архивы из файлов находящихся в этих подпапках и сохранить их в "Основная_папка". При этом: 1. Архив должен содержать только файлы определенного расширения ".ххх". 2. Архив должен именоваться названием файла наибольшего веса каждой отдельной подпапки. 3. Архив должен быть формата zip. 4. Архив должен иметь расширение файла ".yyy". На данный момент использую следующий скрипт, запускаемый в "Основная_папка": Код:
FOR /D %%i IN (*) DO ( Создавать архивы из всех файлов находящихся в этих подпапках и сохранять их в "Основная_папка". Называть архив именем подпапки. Применять расширение ко всем архивам ".yyy". Допускаемые инструменты: WinRAR 7z - предпочтительно Допускаемый вариант решения: CMD/BAT Powershell Заранее спасибо. |
Цитата:
но ведь вес .\Dir1\Dir11 входит в состав веса .\Dir1 когда мы будем искать наибольший это будут естественно корни |
Цитата:
Цитата:
со вторым пунктом тоже как-то не всё понятно. Их таки вместе заархивировать или каждый по отдельности? из того как я понял: Код:
$archive_name = (Get-ChildItem ./*/*.xxx | Sort-Object -Property Length -descending | select -First 1).BaseName |
Цитата:
2. Каждый по отдельности. Дополнительный пример (в живую) под спойлером. Скрытый текст
![]() Цитата:
Пример реализации под спойлером. Скрытый текст
![]() Тут осталось только сделать сортировку по весу файла с последующей выборкой имени у самого крупного файла в папке. Немного усложняем задачу на 1 шаг вперед. Именовать архив нужно используя не fullname файла наибольшего по весу. Как именно нужно: 1. Узнаем fullname файла наибольшего по весу 2. Сравниваем найденый fullname с названием "Подпапки" (первых 6 символов будет достаточно) %var:~0,6%%"=="var2", где var - имя файла, а var2 - имя подпапки, в которой находятся файлы. Тот файл, который проходит проверку - является положительным результатом. Сравнивать, например, можно так: %var:~0,7%%"==%var2 3. Применяем название архива, как "..\%%F.apps", где %%F=var Пока писал, чуть сам не запутался... А может запутался... Прописать это все на деле не хватает опыта. Надеюсь на вашу помощь :) |
А нафига тогда размер файла подтягивать? я уже вообще ничего не розумею. короче вот:
Код:
Get-ChildItem -Directory | ForEach-Object { |
Elven,
Скрытый текст
Код:
Невозможно вызвать метод для выражения со значением NULL. Что-то ему не нравится... Цитата:
|
Конечно будет ругаться. Не может он удалить символы ПОСЛЕ шестого, если символов МЕНЬШЕ 6 (можно выбрать число поменьше).
Далее, скрипт немного таки поменять нужно было (у меня не было пачки apk чтобы потестить на них, за то у меня было много файлов с другим расширением, которые разумеется не находятся у вас, за полным отсутствия присутствия оных). Код:
Get-ChildItem $_/*.ps1 Исправить это и должно заработать. |
Elven, я так понял нужно вот эти имена подпапок найти:
Скрытый текст
C:\USERS\...\DESKTOP\PAPKA ├───Dir0 │ ├───Dir11 (самая большая подпапка в Dir1) │ │ filea │ │ fileb │ │ filec | | │ │ │ ├───Dir12 │ │ fileab │ │ filebc | | | | │ │ │ └───Dir13 │ fileag │ filean │ ├───Dir2 │ ├───Dir21 │ ├───Dir22 │ │ ├───Dir221 (самая большая подпапка в Dir2) │ │ │ fileabb │ │ │ fileanm │ │ │ filebn | | | │ │ │ │ │ └───Dir222 │ └───Dir23 │ filebnm │ filewer │ filejkl | │ └───Dir3 ├───Dir31 │ └───Dir331 (самая большая подпапка в Dir3) │ filedf | filefgh │ └───Dir32 filebnmj |
Цитата:
Сейчас приеду домой и затестим еще раз, только уже на другой системе. Отпишусь. |
alpap, вроде как нужно
0. в каждой подпапке найти самый большой файл с определенным расширением 1. сравнить его имя с именем подпапки в которой он находится (первые шесть символов) 2. заархивировать все файлы с определенным расширением внутри подпапки и назвать архив именем файла с наибольшим размером, задав кастомное расширения какое-то там. more_than_hater, не менее 6 символов должно быть не только у файлов, но и у подпапок в названии. Такую проверку я не добавлял, и так уже для того чтобы выполнить то, что делается в три строчки, наворочено... |
Elven,
Подправил расширения и уменьшил кол-во символов для удаления до 4-х. Скрытый текст
Код:
Get-ChildItem -Directory | ForEach-Object { Выдаваемая ошибка: Скрытый текст
Код:
PS C:\Users\penky> C:\Users\penky\Documents\Raccoon\content\apps\test.ps1 Структура основной папки и пример подпапки (во всех подпапках примерно также): Скрытый текст
![]() |
надо было сразу так сделать...
Код:
$mask = "*.apk" и если снова не запустится - вывод Код:
tree /f /a |
Elven, зачем выполнять 3 раза подряд команду Get-ChildItem $_/$mask?
Код:
$ext = "*.apk" |
Fors1k, ну а как это обычно получается? Дернул один раз - ради этого в переменную загонять как-то... зачем? после этого заметил что еще раз нужно. Потом переписал скрипт еще три раза и забил на это :)
|
Elven, скрипт отлично работает, но есть две проблемки.
1. При замене .zip на .yyy - как я понял из поста Fors1k, можно дообавить команду ren для последующего переименования. Тут ок. Скрытый текст
Код:
Compress-Archive : .apps — неподдерживаемый формат файла архива. .zip — единственный поддерживаемый формат файла архи 2. В некоторых случаях (папка-файл), нужно отрезать более 11 символов, но не все (папка-файл) имеют такую длинну. Скрытый текст
Код:
Исключение при вызове "Remove" с "1" аргументами: "startIndex должен быть меньше, чем длина строки. Есть возможность делать проверку не обрезая длинну, а взяв первые Х символов? P.S. Цитата:
|
1. линуксовый posh не такой капризный - жрет что дали :). значит нужно сначала в зип, а потом переименовывать (см. ниже)
2. не проще тогда искать название папки в названии файла (опять же см. ниже)? Код:
$aext = "*.ps1" |
Elven , Отлично работает, спасибо!
1. Дополнительный вопрос. Можем ли модернизировать скрипт на использование 7z? Конкретно сейчас нужды в этом нет, но в будущем... Попытался внести правки в код: Скрытый текст
Код:
$mask = "*.apk" Но правки встречают меня ошибкой: Скрытый текст
Код:
Start-Process : Не удается найти позиционный параметр, принимающий аргумент "./air.au.com.metro.DumbWaysToDie2-500001 Подскажите, как правильно внести правку? 2. В продолжение смежной темы "сравнение названий" Т.к. у нас в скрипте все-еще идет отборка по размеру файла - попадаются ситуации, когда самый крупный по размеру файл в подпапке - не является нужным. Можем отказаться от сравнения с самым крупным файлом в подпапке и сравнивать имя каждого файла в подпапке с именем самой подпапки? Параллельно изучаю скрипт Ув. Fors1k. Я так понял - у него происходит примерно то, что написал ранее. Скрытый текст
![]() P.S. Код Ув.Fors1k также работает отлично, спасибо! |
Ещё вариант
Код:
$dir = "D:\temp" |
Цитата:
Скрытый текст
Код:
Исключение при вызове "EnumerateFiles" с "3" аргументами: "Не удалось найти часть пути "C:\Users\admin\com.adobe.read |
Цитата:
Цитата:
Цитата:
Код:
$aext = "*.xxx" |
Цитата:
Старый вариант работал в PSv7, но в v5.1 почему-то нет. Fors1k, как вы делаете подсветку кода здесь? |
Цитата:
Цитата:
|
Цитата:
Сделали четко по ТЗ, здесь вопросов нет. В ходе тестирования скриптов Ув. Elven и Ув. Fors1k обнаружил проблему, что отборка по размеру файла - не всегда есть хорошо. Попадаются ситуации, когда самый крупный по размеру файл в подпапке - не является нужным. Ув. Fors1k использовал в своем скрипте метод отбора substring(0,4) - где 0 - с какого символа начинать сравнение и 4 - по какой символ включительно заканчивать сравнение. В сравнении учавствуют все файлы. Т.к. знаний для написания своих команд мне на текущий момент нехватает (читать доки не перечитать) - попробовал использовать строку кода со скрипта Ув. Fors1k, модифицировав ваш, однако на выходе $name не применяется: Скрытый текст
Код:
$dir = "C:\Users\admin\Documents\Raccoon\content\test_apps" Пробовал запускать скрипт через отладку в ISE - ошибку не выводит. Можете разъяснить, почему все "так просто" не происходит? Вроде все переменные совпадают... P.S. Скрипт Ув. Elven закончил работу с 13 папками за 53,9 сек Скрипт Ув. Fors1k закончил работу с 13 папками за 28,7 сек Тоже хотелось бы понять, почему так происходит. Очень "грубо догадываясь" - в скрипте Ув. Elven красиво расписан переход от процедуре к процедуре, из за чего длинна кода увеличена, что способствует уменьшению скорости работы. В это же время, Ув. Fors1k решил не расписывать переходы и сделать код "все в одной строке", из-за чего разобраться в нем чуть сложнее, но работает в разы быстрее. Может кто-то объяснить более внятно, почему такая разница в скорости? Еще раз всем спасибо за потраченное время на проходящего мимо ламера. |
more_than_hater, все гораздо проще - я в массиве два раза ковыряюсь :).
|
Цитата:
Цитата:
То же и с расширением при упаковке. PS7 пофигу, какое расширение файла будет при упаковке, а PS5.1 ругается и требует, чтобы это обязательно было .zip, из-за этого пришлось дополнительно дописывать процедуру переименования. |
Цитата:
Код:
cls Для понимания кода просто переводите слова на русский :) Например: Get-ChildItem $dir -Filter $ext -file = получи дочерние объекты в $dir по фильтру $ext -только файлы. |
Цитата:
Цитата:
Цитата:
|
PS7 ставится рядом, он не заменяет установленный PS5.1.
Код:
# Установить PS 7 |
Господа, приветствую еще раз.
Возникла потребность модифицировать скрипт написанный Вами ранее. Каждая из папок может содержать как старые файлы, так и один единственный файл Самый сложный случай: Если в папке находится несколько файлов с разной датой (день) - то выбирать только самые новые файлы для дальнейшей работы с ними. Если таких файлов несколько (день) - то архивировать их и все так-же переиминовывать архив в .xxx Если такой файл один (день) - то не архивировать его, а просто копировать в ту же папку, где запускается текущий скрипт. Т.е., нужно добавить проверку по дате (newest per day) и по кол-ву файлов внутри этой самой даты. Заранее спасибо. |
Время: 09:10. |
Время: 09:10.
© OSzone.net 2001-