Страница 1 из 36
Рекурсивная распаковка
Добавлено: Вс июл 31, 2011 19:30
D1P
Дано: ветвистое дерево каталогов, вложенность может быть неограниченная. В каталогах файлы, запакованные обычным zip, несколько десятков тысяч всего.
Требуется распаковать все файлы с сохранением структуры каталогов.
Вариант вынести всё через Ctrl+B, распаковать, а потом каким-либо способом восстановить структуру не подходит, потому что такого способа нет.
Как решить задачу?
Добавлено: Вс июл 31, 2011 19:42
Flasher
Пока неясно, куда распаковывать - в родительскую для каждого архива директорию или в новую одноимённую директорию, создаваемую внутри родительской?
Также неясно, что значит "с сохранением структуры"? Подразумевается, что при стандартном подходе содержимое всех архивов перекачует в общую папку, а не родительскую для каждого архива?
Мне кажется стоит подождать
Tol!k, он скорректирует под сеи нужды
этот батник.
Добавлено: Вс июл 31, 2011 20:08
D1P
>Пока неясно, куда распаковывать - в текущую для каждого архива директорию или в новую одноимённую директорию, создаваемую внутри текущей?
Проще всего объяснить так: на месте зипованых файлов должны оказаться раззипованные. Никаких новых директорий, никакого перемещения.
Добавлено: Пн авг 01, 2011 00:55
Tol!k
параметры: "%L" "%%~dpf" -o

важно выделять архивы (поиском или Ctrl+B), а не папку
Добавлено: Пн авг 01, 2011 08:18
D1P
Tol!k писал(а):параметры: "%L" "%%~dpf" -o
Спасибо. Это для твоего батника параметры?
Добавлено: Пн авг 01, 2011 17:44
Flasher
Что-то вчера накидал (ин-ета не было - не мог выложить):
Код: Выделить всё
' Рекурсивная распаковка архивов внутри выделенных каталогов
' Параметры: %L <расширение архива>
'==========================================
Dim FSO, WSH
Set FSO = CreateObject("Scripting.FileSystemObject")
Set WSH = CreateObject("WScript.Shell")
Proga = WSH.ExpandEnvironmentStrings("%COMMANDER_PATH%\Utils\7-Zip\7z.exe")
With FSO.OpenTextFile(WScript.Arguments(0), 1)
Do While Not .AtEndOfStream
F = Trim(.ReadLine)
If F <> "" Then
If FSO.FolderExists(F) Then ForFolder FSO.GetFolder(F)
End If
Loop
.Close
End With
WSH.Popup "Распаковка завершена!", 1.4, "Результат", 64
Set FSO = Nothing
Set WSH = Nothing
WScript.Quit
Sub ForFolder(Folder)
Dim N
For Each N In Folder.Files
ForFile N
Next
For Each N In Folder.SubFolders
ForFolder N
Next
End Sub
Sub ForFile(File)
If LCase(FSO.GetExtensionName(File)) = LCase(WScript.Arguments(1)) Then WSH.Run """" & Proga & """x """ & File & """ -o""" & File.ParentFolder & "\"" -y", 0, True
End Sub
См., чтобы путь к 7z.exe соответствовал.
Добавлено: Пн авг 01, 2011 18:54
Tol!k
D1P писал(а):Tol!k писал(а):параметры: "%L" "%%~dpf" -o
Спасибо. Это для твоего батника параметры?
Да,
http://forum.wincmd.ru/viewpost.php?p=67240 Только без
-o Извини, я похоже, уже спал:
-o — каждый архив в отдельную папку с именем архива
Добавлено: Пн авг 01, 2011 21:15
D1P
Tol!k
Спасибо, отличнейшим образом всё сработало.
Flasher
Тебе тоже спасибо.
Добавлено: Пн авг 01, 2011 21:17
Flasher
D1P
Пож-та. Работа скрипта соответствует ТЗ, или что-то не так?
Добавлено: Вт авг 02, 2011 10:01
Batya
Flasher
Пару советов:
1. При сравнении расширений "FSO.GetExtensionName(FilePath) = WScript.Arguments(1)" лучше приводить к одному регистру "UCase(FSO.GetExtensionName(FilePath)) = UCase(WScript.Arguments(1))" или использовать InStr "InStr(1, FSO.GetExtensionName(FilePath), WScript.Arguments(1), 1) > 0".
2. Думаю, что для поставленной задачи, т.к. арховов "несколько десятков тысяч", лучше использовать не параллельную распаковку, а последовательную. При вызове WSH.Run укажи третий параметр со значением True.
Добавлено: Вт авг 02, 2011 12:23
Flasher
Batya
1. ОК.
2. Изначально стояло True, просто кое-какие глюки c 7z были, процесс висеть оставался, но там причина, видимо, в другом была. Ещё вчера хотел вернуть, пост пачкать не хотелось.

Хоть, конечно, для небольшого числа архивов параллельная распаковка проходит быстрее, не учесть большие списки нельзя, поэтому возвращаю True на место. К тому же сообщение будет появляться своевременно.
Добавлено: Вт авг 02, 2011 19:11
D1P
Flasher
До твоего скрипта руки не дошли, всё сделал батником.
Добавлено: Вт авг 02, 2011 19:34
Flasher
D1P
А зря, сэкономил бы себе время.
2
All
На всякий случай сообщаю тем, кому выгодней (например, мне) распаковывать каждый архив в создаваемую папку с базовым именем архива:
замените нижнюю процедуру на эту:
Код: Выделить всё
Sub ForFile(File)
If LCase(FSO.GetExtensionName(File)) = LCase(WScript.Arguments(1)) Then
On Error Resume Next
NF = FSO.CreateFolder(File.ParentFolder & "\" & FSO.GetBaseName(File) & "\")
WSH.Run """" & Proga & """ x """ & File & """ -o""" & NF & """ -y", 0, True
End If
End Sub
Добавлено: Чт авг 04, 2011 04:05
Volniy
Batya писал(а):
1. При сравнении расширений "FSO.GetExtensionName(FilePath) = WScript.Arguments(1)" лучше приводить к одному регистру "UCase(FSO.GetExtensionName(FilePath)) = UCase(WScript.Arguments(1))" или использовать InStr "InStr(1, FSO.GetExtensionName(FilePath), WScript.Arguments(1), 1) > 0"
...или использовать специально заточенную для сравнения строк функцию
StrComp: Код: Выделить всё
If StrComp(FSO.GetExtensionName(FilePath), WScript.Arguments(1) ,1) = 0 Then
Добавлено: Сб авг 13, 2011 23:56
Flasher
Подумал, пусть тут тоже будет:
Код: Выделить всё
'•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
' Распаковка выделенных архивов и архивов в структуре
' выделенных каталогов в одноименные папки рядом с архивами
' Параметры: %L <расширения архивов через запятую>
' Пример: %L 7z,7zip,arc,bzip2,rar,zip
' Автор - Flasher ©
'•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
Dim WSH, FSO
Set WSH = CreateObject("WScript.Shell")
Set FSO = CreateObject("Scripting.FileSystemObject")
Proga = WSH.ExpandEnvironmentStrings("%COMMANDER_PATH%\Utils\7-Zip\7z.exe")
With WScript.Arguments
On Error Resume Next
List = .Item(0)
Filt = .Item(1)
If Len(List) > 0 And .Count < 2 Then
MsgBox "Укажите оба параметра!",_
vbExclamation, " Рекурсивная упаковка"
Wscript.Quit
End If
End With
If Err.Number > 0 Then
MsgBox "Не выбраны элементы для распаковки!", vbExclamation,_
" Рекурсивная пофайловая распаковка"
End If
Set Dict = CreateObject("Scripting.Dictionary")
Exts = "7z, 7zip, arj, bz2, bzip2, cab, chm, chw, cpio, cramfs, deb, dmg, doc, exe, fat, gz, gzip, hfs, hxs, iso, lha, lzma, mbr, msi, ntfs, ppt, rar, rpm, scap, squashfs, swm, tar, taz, tbz, tbz2, tgz, vhd, wim, xar, xls, xz, zip"
For Each E in Split(Exts, ", ")
Dict.Add Trim(E), ""
Next
With FSO.OpenTextFile(List, 1)
Do While Not .AtEndOfStream
F = Trim(.ReadLine)
If F <> "" Then
If FSO.FolderExists(F) Then
ForFolder FSO.GetFolder(F)
Else ForFile F
End If
End If
Loop
.Close
End With
Set Dict = Nothing
WSH.Popup "Распаковка завершена!", 1.4 , "Результат", 64
Set WSH = Nothing
Set FSO = Nothing
WScript.Quit
Sub ForFolder(Folder)
Dim N
For Each N In Folder.SubFolders
ForFolder N
Next
For Each N In Folder.Files
ForFile N
Next
End Sub
Sub ForFile(File)
For Each Fi in Split(Filt,",")
If StrComp(Fi,FSO.GetExtensionName(File),1) = 0 And Dict.Exists(LCase(Fi)) Then
NF = FSO.CreateFolder(FSO.GetParentFolderName(File) & "\" & FSO.GetBaseName(File) & "\" )
WSH.Run """" & Proga & """ x """ & File & """ -o""" & NF & """ -y", 0, True
End If
Next
End Sub
Распаковываться будут архивы только с поддерживаемыми форматами (42 расширения).