Витяг вкладених zip-файлів


15

У мене є численні архіви zip, кожен з яких містить ряд архівів zip. Який найкращий спосіб рекурсивно витягувати всі файли, що містяться в цьому поштовому архіві та його дочірніх поштових архівах, які самі по собі не є поштовими архівами?


що ви маєте на увазі, витягуючи речі, які не є поштовими файлами? Ви хочете скопіювати їх в інше місце?
phunehehe

Я не вважаю ваші вимоги зрозумілими. Я вважаю Шона Дж. Гоффа і моє тлумачення приблизно однаково вірогідним. Не могли б ви уточнити?
Жил 'SO- перестань бути злим'

@Gilles: Вибачте, так, це було трохи незрозуміло. Я трохи його змінив, сподіваюсь, його тепер зрозуміліше.
oadams

Я збирався опублікувати відповідь, але я вважаю, що це має стати коментарем: Вкладені архіви збільшують потрібний вам простір! Ви, мабуть, маєте на увазі формат файлу Zip, а не лише gzip. кожен zip-файл вже стислий, стискаючи їх знову, просто створюється більше накладних витрат, ефективно збільшуючи необхідний простір.
полеміс

Так, я цього не зробив: P. На жаль, я піддаюся цьому химерному способу розповсюдження файлів.
oadams

Відповіді:


13

Це дозволить витягнути всі поштові файли в поточний каталог, виключаючи поштові файли, що містяться в них.

find . -type f -name '*.zip' -exec unzip -- '{}' -x '*.zip' \;

Хоча це витягує вміст у поточний каталог, не всі файли в цьому каталозі будуть суворо потрапляти, оскільки вміст може містити підкаталоги.

Якщо ви дійсно хотіли, щоб усі файли були строго в поточному каталозі, ви можете запустити

find . -type f -mindepth 2 -exec mv -- '{}' . \;

Примітка. Це будуть файли клобіру, ​​якщо в різних каталогах є два з однаковим іменем.

Якщо ви хочете рекурсивно витягувати всі zip-файли та зіпси, що містяться в ньому, наступне витягує всі поштові файли з поточного каталогу та всі цип-файли, що містяться в них, у поточний каталог.

while [ "`find . -type f -name '*.zip' | wc -l`" -gt 0 ]
do
    find . -type f -name "*.zip" -exec unzip -- '{}' \; -exec rm -- '{}' \;
done

цей цикл, хоча цикл мені дуже допоміг у змаганнях з етичного хакерства, де вони підготували вкладений zip-файл, який пройшов 31337 рівнів глибше, дякую!
peedee

2
вам може сподобатися цей варіант, який я використовую для рекурсивного вилучення вмісту з вкладених файлів вуха, війни, jar: gist.github.com/tyrcho/479c18795d997c201e53 Основна відмінність - це створення вкладеної папки для кожного архіву. while [ "знайти. -типу f -ім'я '*.? ar' | wc -l" -gt 0 ]; do find -type f -name "*.?ar" -exec mkdir -p '{}.dir' \; -exec unzip -d '{}.dir' -- '../{}' \; -exec rm -- '{}' \;; done
Мішель Давіот

4

Наскільки я розумію, у вас є поштові архіви, які самі містять поштові архіви, і ви хочете розпаковувати вкладені блискавки щоразу, коли їх витягуєте.

Ось bash 4 скрипт, який розпаковує всі ZIP-файли в поточному каталозі та його підкаталогах рекурсивно, видаляє кожен zip-файл після його розпакування та продовжує тривати, поки є поштові файли. Файл zip у підкаталозі вилучається відносно цього підкаталогу. Попередження: протестовано, зробіть резервну копію оригінальних файлів, перш ніж випробувати її або замінити rm, перемістивши zip-файл поза деревом каталогу .

shopt -s globstar nullglob
while set -- **/*.zip; [ $# -ge 1 ] do
  for z; do
    ( cd -- "$(dirname "$z")" &&
      z=${z##*/} &&
      unzip -- "$z" &&
      rm -- "$z"
    )
  done
done

Сценарій також буде працювати в zsh, якщо ви заміните shoptрядок на setopt nullglob.

Ось портативний еквівалент. Умова припинення є дещо складною, тому findщо спонтанно не повертає статус, щоб вказати, чи знайшов файли. Попередження: як зазначено вище.

while [ -n "$(find . -type f -name '*.zip' -exec sh -c '
    cd "${z%/*}" &&
    z=${z##*/} &&
    unzip -- "$z" 1>&2 &&
    rm -- "$z" &&
    echo 1
')" ]; do :; done

1

unzipцього не робити, тому що UNIX спосіб - це робити одне і робити це добре, а не обробляти всі божевільні особливі випадки у кожному інструменті. Таким чином, вам потрібно скористатися оболонкою (яка добре виконує завдання "зв'язати речі". Це робить його питанням програмування, і оскільки всі можливі питання програмування відповіли на StackOverflow, тут: Як ви рекурсивно розпаковуєте архіви в каталозі та його підкаталогах з командного рядка Unix?


1
Я б точно не називав "використання оболонки" питання програмування, а "сценарій оболонки" вказаний у FAQ, як на тему
Michael Mrozek

Я не мав на увазі, що це взагалі поза темою, я просто хотів виправдати, чому це тематично в StackOverflow.
Томас Темель

1

Цей скрипт perl витягує кожен .zip файл у свій власний підкаталог. Запускайте сценарій не один раз для обробки вкладених zip-файлів. Він не видаляє .zip файли після вилучення, але ви можете внести ці зміни, додавши виклик unlink ().

#!/usr/bin/perl -w

# This script unzips all .zip files it finds in the current directory
# and all subdirectories.  Contents are extracted into a subdirectory
# named after the zip file (eg. a.zip is extracted into a/).
# Run the script multiple times until all nested zip files are
# extracted.  This is public domain software.

use strict;
use Cwd;

sub process_zip {
    my $file = shift || die;
    (my $dir = $file) =~ s,/[^/]+$,,;
    (my $bare_file = $file);
    $bare_file =~ s,.*/,,;
    my $file_nopath = $bare_file;
    $bare_file =~ s,\.zip$,,;
    my $old_dir = getcwd();
    chdir($dir) or die "Could not chdir from '$old_dir' to '$dir': $!";
    if (-d $bare_file) {
        chdir($old_dir);
        # assume zip already extracted
        return;
    }
    mkdir($bare_file);
    chdir($bare_file);
    system("unzip '../$file_nopath'");
    chdir($old_dir);
}

my $cmd = "find . -name '*.zip'";
open(my $fh, "$cmd |") or die "Error running '$cmd': $!";
while(<$fh>) {
    chomp;
    process_zip($_);
}

1

Найпростіший спосіб - це використовувати atool: http://www.nongnu.org/atool/ Це дуже хороший сценарій, який використовує програми zip, unzip, tar, rar тощо для отримання будь-якого архіву.

Використовуйте atool -x package_name.zipдля розпакування їх усіх або, якщо ви хочете використовувати його в каталозі з багатьма поштовими файлами, використовуйте простий forцикл:

for f in *; do atool -x $f; fi(перед цим вам доведеться cdпотрапити в потрібний каталог із zip-файлами).


atoolПоведінка тут не суттєво відрізняється від розпакування, я б сказав, він не рекурсивно витягує ZIP-файли.
Томас Темель

@Thomas Themel: Ви впевнені, що він не рекурсивно витягує ZIP-файли? Він може витягувати з деб-файлів tar.gz рекурсивно, але у мене немає часу, щоб перевірити його за допомогою вкладених zip-архівів: \

0

Ви хочете бути обережними, автоматично розпаковуючи поштові файли всередині zip-файлів:

http://research.swtch.com/2010/03/zip-files-all-way-down.html

Можна створити zip-файл, який видає zip-файл як вихід, який створює zip-файл як вихідний, і т. Д. І т.д. і т. Д. Тобто, ви можете зробити zip-файл, який є фіксованою маззю "розпакувати" програму.

Крім того, я, начебто, пригадую людей, які роблять zip-файли, які б "вибухнули", тобто дуже маленький zip-файл розпакував би багатогігабайт виводу. Це грань методу компресії.


0

Можливо, це допоможе (працювало для мене):

function unzipAll(){

# find and count archives
archLst=`find . -type f -name "*.*ar"`
archLstSize=`echo $archLst| awk 'END{print NF}'`

# while archives exists do extract loop
while [ "$archLstSize" -gt 0 ]; do

# extract and remove all archives (found on single iteration)
for x in $archLst; do 
mv "${x}" "${x}_";
unzip "${x}_" -d "${x}" && rm "${x}_"; 
done; #EO for

# find and count archives
archLst=`find . -type f -name "*.*ar"`
archLstSize=`echo $archLst| awk 'END{print NF}'`

done #EO while

}

0

Мені потрібно було таке рішення, як Giles 'з 2010 року, за винятком того, що мені потрібно було зберегти структуру папок, а не розпакувати все до каталогу верхнього рівня. Ось мій погляд на його, додавши / змінивши три рядки:

#!/bin/bash
shopt -s globstar nullglob
while set -- **/*.zip; [ $# -ge 1 ]
do
    for z
    do
        ( cd -- "$(dirname "$z")" &&
            z=${z##*/} &&
            cp -- "$z" "$z".bak &&
            mkdir -- "$z"dir &&
            unzip -- "$z" -d "$z"dir &&
            rm -- "$z"
        )
    done
done

0

Ознайомтеся з цією утилітою nzip на базі Java для вкладених zip-файлів. Витягування та стискання вкладених блискавок можна легко виконати за допомогою наступних команд

java -jar nzip.jar -c список -s readme.zip

java -jar nzip.jar -c витяг -s "C: \ project \ readme.zip" -t readme

java -jar nzip.jar -c компрес -s readme -t "C: \ project \ readme.zip"

PS. Я автор і буду радий швидко виправити будь-які помилки.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.