Mam liczne archiwa zip, z których każde zawiera wiele archiwów zip. Jaki jest najlepszy sposób rekurencyjnego wyodrębnienia wszystkich plików zawartych w tym archiwum zip i jego podrzędnych archiwach zip, które same nie są archiwami zip?
Mam liczne archiwa zip, z których każde zawiera wiele archiwów zip. Jaki jest najlepszy sposób rekurencyjnego wyodrębnienia wszystkich plików zawartych w tym archiwum zip i jego podrzędnych archiwach zip, które same nie są archiwami zip?
Odpowiedzi:
Spowoduje to wyodrębnienie wszystkich plików zip do bieżącego katalogu, z wyjątkiem zawartych w nich plików zip.
find . -type f -name '*.zip' -exec unzip -- '{}' -x '*.zip' \;
Mimo że wyodrębnia to zawartość do bieżącego katalogu, nie wszystkie pliki znajdą się w tym katalogu ściśle, ponieważ zawartość może zawierać podkatalogi.
Jeśli naprawdę chcesz, aby wszystkie pliki były ściśle w bieżącym katalogu, możesz uruchomić
find . -type f -mindepth 2 -exec mv -- '{}' . \;
Uwaga: spowoduje to zamknięcie plików, jeśli w różnych katalogach są dwa o tej samej nazwie.
Jeśli chcesz rekurencyjnie wyodrębnić wszystkie pliki zip i zawarte w nich zamki błyskawiczne, poniższe wypakuje wszystkie pliki zip z bieżącego katalogu i wszystkie zawarte w nich zamki błyskawiczne do bieżącego katalogu.
while [ "`find . -type f -name '*.zip' | wc -l`" -gt 0 ]
do
find . -type f -name "*.zip" -exec unzip -- '{}' \; -exec rm -- '{}' \;
done
while [ "
odnaleźć . -type f-name '*.? ar' | wc-l" -gt 0 ]; do find -type f -name "*.?ar" -exec mkdir -p '{}.dir' \; -exec unzip -d '{}.dir' -- '../{}' \; -exec rm -- '{}' \;; done
O ile rozumiem, masz archiwa zip, które same zawierają archiwa zip i chciałbyś rozpakować zagnieżdżone zamki błyskawiczne za każdym razem, gdy są one rozpakowywane.
Oto skrypt bash 4, który rozpakowuje wszystkie zamki błyskawiczne w bieżącym katalogu i jego podkatalogach rekurencyjnie, usuwa każdy plik zip po rozpakowaniu i działa tak długo, jak długo są pliki zip. Plik zip w podkatalogu jest wyodrębniany względem tego podkatalogu. Ostrzeżenie: niesprawdzone, wykonaj kopię zapasową oryginalnych plików przed wypróbowaniem lub zamień rm
, przenosząc plik zip poza drzewo katalogów .
shopt -s globstar nullglob
while set -- **/*.zip; [ $# -ge 1 ] do
for z; do
( cd -- "$(dirname "$z")" &&
z=${z##*/} &&
unzip -- "$z" &&
rm -- "$z"
)
done
done
Skrypt będzie również działał w Zsh, jeśli zastąpisz shopt
linię setopt nullglob
.
Oto przenośny odpowiednik. Warunek zakończenia jest nieco skomplikowany, ponieważ find
nie spontanicznie zwraca status wskazujący, czy znalazł jakieś pliki. Ostrzeżenie: jak wyżej.
while [ -n "$(find . -type f -name '*.zip' -exec sh -c '
cd "${z%/*}" &&
z=${z##*/} &&
unzip -- "$z" 1>&2 &&
rm -- "$z" &&
echo 1
')" ]; do :; done
unzip
nie robi tego, ponieważ UNIX to zrobić jedną rzecz i zrobić to dobrze, a nie obsługiwać wszystkich szalonych specjalnych przypadków w każdym narzędziu. Dlatego musisz użyć powłoki (która dobrze wykonuje zadanie „powiązania ze sobą”). To sprawia, że jest to pytanie programistyczne, a ponieważ na StackOverflow udzielono odpowiedzi na WSZYSTKIE możliwe pytania programistyczne, tutaj: Jak rekurencyjnie rozpakowujesz archiwa w katalogu i jego podkatalogach z wiersza poleceń Uniksa?
Ten skrypt perla wyodrębni każdy plik .zip do własnego podkatalogu. Uruchom skrypt więcej niż jeden raz, aby obsłużyć zagnieżdżone pliki zip. Nie usuwa plików .zip po rozpakowaniu, ale możesz to zmienić, dodając wywołanie 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($_);
}
Najprostszym sposobem jest użycie atool: http://www.nongnu.org/atool/ Jest to bardzo dobry skrypt, który używa programów zip, unzip, tar, rar itp. W celu wyodrębnienia dowolnego archiwum.
Użyj, atool -x package_name.zip
aby rozpakować je wszystkie lub jeśli chcesz użyć go w katalogu z wieloma plikami zip, użyj prostej for
pętli:
for f in *; do atool -x $f; fi
(będziesz musiał przejść cd
do pożądanego katalogu z plikami zip przed użyciem).
atool
Zachowanie tutaj nie różni się znacząco od rozpakowania powiedziałbym, że nie rekurencyjnie wyodrębnia plików ZIP.
Musisz zachować ostrożność, automatycznie rozpakowując pliki zip wewnątrz plików zip:
http://research.swtch.com/2010/03/zip-files-all-way-down.html
Możliwe jest wymyślenie pliku zip, który tworzy plik zip jako plik wyjściowy, który tworzy plik zip jako plik wyjściowy itp. Itd. Oznacza to, że możesz utworzyć plik zip, który jest stałą cechą „rozpakowania” programu.
Wydaje mi się też, że pamiętam ludzi tworzących pliki zip, które „eksplodowałyby”, czyli bardzo mały plik zip rozpakowałby się do wielu gigabajtów danych wyjściowych. Jest to aspekt metody kompresji.
Może to pomoże (działało dla mnie):
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
}
Potrzebowałem rozwiązania takiego jak Giles z 2010 roku, z wyjątkiem tego, że musiałem zachować strukturę folderów, a nie rozpakowywać wszystkiego do katalogu najwyższego poziomu. Oto moje spojrzenie na jego z trzema liniami dodanymi / zmienionymi:
#!/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
Pobierz to nzip oparte na Javie narzędzie do zagnieżdżonych plików zip. Wyodrębnianie i kompresowanie zagnieżdżonych zamków błyskawicznych można łatwo wykonać za pomocą następujących poleceń
java -jar nzip.jar -c list -s readme.zip
java -jar nzip.jar -c extract -s "C: \ project \ readme.zip" -t readme
java -jar nzip.jar -c kompres -s readme -t "C: \ project \ readme.zip"
PS. Jestem autorem i chętnie naprawię wszelkie błędy.