PDA

Показать полную графическую версию : Заменить каждую крайнюю папку в дереве имеющую файлы архивом.


adgeuk
31-07-2021, 21:50
Пытаюсь создать архивы только для самых глубоко лежащих папок в дереве, и сохранить их там же.

Сначала, через поиск в Total Commander нахожу все конечные папки у которых нет подпапок.
Затем, выделяю все результаты поиска и создаю архив с галочкой "каждый файл в отдельный архив" чтобы каждая папка архивировалась отдельно.
По идее, каждая выделенная в результатах папка должна быть заархивирована в том же месте где и лежит.
Однако, все архивы кидаются в кучу, в одно место.

Пробовал и через результаты поиска в Total Commander и через результаты поиска в эксплорере, то же самое.
Как бы это провернуть?

Iska
31-07-2021, 22:16
По идее, каждая выделенная в результатах папка должна быть заархивирована в том же месте где и лежит. »
С чего бы это вдруг? Должно быть именно так, как оно и происходит:
все архивы кидаются в кучу, в одно место. »
только не «в кучу», а в текущем каталоге.

Как бы это провернуть? »
Скриптом. Хотя лично мне цель сего действа малопонятна.

adgeuk
01-08-2021, 00:19
Хотя лично мне цель сего действа малопонятна. »
Мне нужно сохранить на облаке mail.ru большую структуру папок с фотографиями, причём сохранить так чтобы эти фотки не отсвечивались в разделе галерея когда я пользуюсь облаком на телефоне. Для этого мне нужно хранить их там в заархивированном виде. Делать один большой архив или образ папки я не могу по двум причинам. Во первых, на облаке есть ограничение - любой файл не может быть больше 4ГБ. Во вторых, в будущем, при скачивании архива на ПК, хочется иметь возможность быстрого просмотра фоток без распаковки всего архива. Поэтому, предпочтительно иметь много маленьких архивов, но без потери структуры дерева.

только не «в кучу», а в текущем каталоге »
Я думал что каждый архив должен сохраниться в своём текущем каталоге, как если бы я последовательно архивировал каждую из этих папок по отдельности.

Скриптом »
Сложновато для меня, но можно попробовать.

Iska
01-08-2021, 02:10
Сделайте многотомный архив с шифрованием (в том числе имён файлов). Это решит обе Ваши проблемы зараз.
Total Commander «умеет» смотреть внутрь архива без распаковки его целиком. Эскизы Вы внутри архива, понятно, не получите, но, вот, QuickView в соседней панели — вполне:

https://i.imgur.com/3djwiWC.png

adgeuk
01-08-2021, 14:31
Сделайте многотомный архив с шифрованием (в том числе имён файлов) »
а почему именно с шифрованием?

Многотомный архив это выход, но хочется чтобы каждая тематическая папка с фотографиями была отдельным архивом.
Так удобнее и скачивать и делиться.

Эскизы Вы внутри архива, понятно, не получите »
Архиватор HaoZip (https://soft.mydiv.net/win/files-HaoZip.html) умеет показывать эскизы фотографий в архивах.
Но для просмотра отдельно взятой фотографии "в полный рост" ему требуется распаковывать архив.

Iska
01-08-2021, 17:08
а почему именно с шифрованием? »
Дабы выполнить это требование:
причём сохранить так чтобы эти фотки не отсвечивались в разделе галерея когда я пользуюсь облаком на телефоне. »
Правильно?

Архиватор HaoZip умеет показывать эскизы фотографий в архивах.
Но для просмотра отдельно взятой фотографии "в полный рост" ему требуется распаковывать архив. »
Нет. Только если архив solid (непрерывный). В противном случае нужно извлечь в каталог временных файлов только файл этой одной фотографии. Это относится к любым архивам.

Многотомный архив это выход, но хочется чтобы каждая тематическая папка с фотографиями была отдельным архивом.
Так удобнее и скачивать и делиться. »
Вы уверены, что у Вас не найдётся каталога, для которого архив займёт более 4 Gb?

Iska
01-08-2021, 17:33
В общем, я предлагаю Вам попробовать немного иначе, а именно: упаковывать в архив содержимое файлов каждого каталога, в котором есть файлы.

На PowerShell:
function ScanSubFolder($oDirectoryInfo) {
if($oDirectoryInfo.GetDirectories().Count -ne 0) {
foreach($oSubDirectoryInfo in $oDirectoryInfo.GetDirectories()) {
ScanSubFolder $oSubDirectoryInfo
}
}

if($oDirectoryInfo.GetFiles().Count -ne 0) {
"$($oDirectoryInfo.FullName)\$($oDirectoryInfo.Name).zip"
Compress-Archive -Path "$($oDirectoryInfo.FullName)\*.*" -DestinationPath "$($oDirectoryInfo.FullName)\$($oDirectoryInfo.Name).zip" -CompressionLevel Optimal
}
}

$oDirectoryInfo = [System.IO.DirectoryInfo]::new('C:\Мои проекты\0349')
ScanSubFolder $oDirectoryInfo

adgeuk
01-08-2021, 21:39
сохранить так чтобы эти фотки не отсвечивались в разделе галерея »
Просто фотки, которые сохранены на облаке mail.ru без архивации в любом случае будут отсвечивать в галерее.
А мне это не нужно, так как эти фото по работе, а галерею я хочу использовать для личных фото.

Вы уверены, что у Вас не найдётся каталога, для которого архив займёт более 4 Gb? »
Пока такого не было, но в будущем, возможно.

Спасибо за код, попробую и отпишусь.

adgeuk
02-08-2021, 14:49
Iska, большое спасибо за помощь!
В целом, всё отлично!

Во время работы были ошибочки с двумя папками:

1.
"Путь не существует или является недоступным путём в файловой системе"
(возможно из-за символа квадратных скобок в имени, не уверян)

2.
"Невозможно преобразовать указанное значение DateTimeOffset в отметку времени ZIP-файла"

Но это не проблема, я упаковал эти два архива вручную.

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

Ещё раз, спасибо!

Iska
02-08-2021, 15:55
"Путь не существует или является недоступным путём в файловой системе"
(возможно из-за символа квадратных скобок в имени, не уверян) »
Возможно. Покажите здесь эти пути.

"Невозможно преобразовать указанное значение DateTimeOffset в отметку времени ZIP-файла" »
Тут надо «копать», не сталкивался.

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

И после архивирования, хочу сделать чтобы папки с оригиналами удалялись. »
Э… Не надо. Ни оригиналы не надо из этого же скрипта удалять, ни каталоги (особенно в данной рекурсивной реализации).

adgeuk
02-08-2021, 16:05
Э… Не надо. »
Понял, удалить можно и после.

Покажите здесь эти пути. »

Ошибка "Путь не существует или является недоступным путём в файловой системе" для пути
"E:\Пикачу Работа\Пикачу Работа\FOTKI\Latvia\Depils\2009\Зебра. Ищейка\Iwejka.Zebra [3.5.09"

Iska
02-08-2021, 16:45
adgeuk, там именно одна скобка? Для какой именно строки кода (приведите её) возникает ошибка?

adgeuk
02-08-2021, 17:05
там именно одна скобка? Для какой именно строки кода (приведите её) возникает ошибка? »
Да, скобка одна.

Compress-Archive : Путь "E:\Пикачу Работа\Пикачу Работа\FOTKI\Latvia\Depils\2009\3e6pa. Ищейка\Iwejka.Zebra[3.5.09" не существует или является недопустимым путем в файловой системе.
строка:10 знак:9
+ Compress-Archive -Path "$($oDirectoryInfo.FullName)\*.*" -Des ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (E:\Пикачу Работа\...ka.Zebra[3.5.09:String) [Compress-Archive], InvalidOperationException
+ FullyQualifiedErrorId : ArchiveCmdletPathNotFound,Compress-Archive

Iska
03-08-2021, 03:45
Угу, ясно. Вот за это я не люблю языки с терминаторными строками, не знаешь заранее, где и из-за чего «рванёт».

Сейчас пытаюсь разобраться в коде, чтобы сохранять архивы не в той же папке где лежат архивируемые фотографии, а на одну папку выше, то есть рядом с папкой источником. »
Попробуем. »
Попробовал. Для корректной работы с таким условием архив надо будет создавать на «спуске» рекурсии, а не на «подъёме» из неё.

2. "Невозможно преобразовать указанное значение DateTimeOffset в отметку времени ZIP-файла" »
Судя по всему, проблема связана с .Net API — ZipArchiveEntry.LastWriteTime Property (System.IO.Compression) | Microsoft Docs (https://docs.microsoft.com/en-us/dotnet/api/system.io.compression.ziparchiveentry.lastwritetime?view=net-5.0):
Exceptions

ArgumentOutOfRangeException

An attempt was made to set this property to a value that is either earlier than 1980 January 1 0:00:00 (midnight) or later than 2107 December 31 23:59:58 (one second before midnight).

Remarks

When you create a new entry from an existing file by calling the CreateEntryFromFile method, the LastWriteTime property for the entry is automatically set to the last time the file was modified. When you create a new entry programmatically by calling the CreateEntry method, the LastWriteTime property for the entry is automatically set to the time of execution. If you modify the entry, you must explicitly set the LastWriteTime property if you want the value to reflect the time of the latest change.

When you set this property, the DateTimeOffset value is converted to a timestamp format that is specific to zip archives. This format supports a resolution of two seconds. The earliest permitted value is 1980 January 1 0:00:00 (midnight). The latest permitted value is 2107 December 31 23:59:58 (one second before midnight). If the value for the last write time is not valid, the property returns a default value of 1980 January 1 0:00:00 (midnight).
То есть, какие-то из файлов, помещаемых в архив, у Вас имеют дату последней записи ранее этого указанного минимального значения. Лезть в это не хочу.

Пробуйте:
function ScanSubFolder($oDirectoryInfo) {
if($oDirectoryInfo.GetFiles().Count -ne 0) {
"$($oDirectoryInfo.Parent.FullName)\$($oDirectoryInfo.Name).zip"

$sSourcePath = [WildcardPattern]::Escape($oDirectoryInfo.FullName) + '\*.*'
$sDestPath = [WildcardPattern]::Escape("$($oDirectoryInfo.Parent.FullName)\$($oDirectoryInfo.Name).zip")

Compress-Archive -Path $sSourcePath -DestinationPath $sDestPath -CompressionLevel Optimal
}

if($oDirectoryInfo.GetDirectories().Count -ne 0) {
foreach($oSubDirectoryInfo in $oDirectoryInfo.GetDirectories()) {
ScanSubFolder $oSubDirectoryInfo
}
}
}

$oDirectoryInfo = [System.IO.DirectoryInfo]::new('C:\Мои проекты\0349')
ScanSubFolder $oDirectoryInfo

adgeuk
03-08-2021, 12:05
Iska, безумно Вам благодарен!
Буду пробовать.




© OSzone.net 2001-2012