İç içe geçmiş zip dosyalarını ayıklama


15

Her biri bir dizi zip arşivi içeren çok sayıda zip arşivim var. Bu zip arşivi ve alt zip arşivlerinde bulunan ve zip arşivlerinin kendisi olmayan tüm dosyaları özyinelemeli olarak çıkarmanın en iyi yolu nedir?


zip dosyası olmayan şeyleri çıkararak ne demek istiyorsun? onları başka bir yere mi kopyalamak istiyorsun?
phunehehe

Gereksinimlerinizi net bulmuyorum. Ben bulmak Shawn J. Goff ve benim eşit olasılıkla ilgili yorumunu. Açıklığa kavuşturabilir misiniz?
Gilles 'SO- kötü olmayı bırak'

@Gilles: Üzgünüm, evet biraz belirsizdi. Biraz değiştirdim, umarım şimdi daha açıktır.
oadams

Bir cevap gönderecektim, ama bunun bir yorum olarak gitmesi gerektiğine inanıyorum: İç İçe Arşivler ihtiyacınız olan alanı arttırıyor ! Muhtemelen Zip dosyası biçimini kastediyorsunuz, sadece gzip değil. her zip dosyası zaten sıkıştırılmış, tekrar sıkıştırılmış, sadece daha fazla ek yük oluşturur, gerekli alanı etkili bir şekilde artırır.
Kasım'da polemon

Evet, ben yapmadım: P. Ne yazık ki dosyaları dağıtmanın bu garip yoluna maruz kaldım.
10:56

Yanıtlar:


13

Bu, içerdiği zip dosyaları hariç tüm zip dosyalarını geçerli dizine çıkarır.

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

Bu, içeriği geçerli dizine ayıklasa da, içerikler alt dizinler içerebileceğinden, tüm dosyalar kesinlikle bu dizinde sonuçlanmaz.

Tüm dosyaları kesinlikle geçerli dizinde istiyorsanız, çalıştırabilirsiniz.

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

Not: farklı dizinlerde aynı ada sahip iki dosya varsa, dosyalarda tıkanma olur.

İçinde bulunan tüm zip dosyalarını ve fermuarları özyinelemeli olarak ayıklamak isterseniz, aşağıdakiler geçerli dizindeki tüm zip dosyalarını ve içerdiği tüm fermuarları geçerli dizine ayıklar.

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

Bu süre döngü bana 31337 seviyeleri derin olacak bir yuvalanmış zip dosyası hazırlamıştı etik hack yarışmasında çok yardımcı oldu, teşekkürler!
peedee

2
iç içe kulak, savaş, kavanoz dosyalarından özyinelemeli olarak içerik ayıklamak için kullandığım bu varyantı beğenebilirsiniz : gist.github.com/tyrcho/479c18795d997c201e53 Büyük fark, her arşiv için iç içe bir klasör oluşturmasıdır. while [ "bulmak. tipi f-adı '*.? ar' | wc -l" -gt 0 ]; do find -type f -name "*.?ar" -exec mkdir -p '{}.dir' \; -exec unzip -d '{}.dir' -- '../{}' \; -exec rm -- '{}' \;; done
Michel Daviot

4

Anladığım kadarıyla, kendilerinde zip arşivleri içeren zip arşivleriniz var ve her çıkarıldığında iç içe fermuarları açmak istiyorsunuz.

Burada, geçerli dizindeki ve alt dizinlerindeki tüm fermuarları yinelemeli olarak açan, her zip dosyasını sıkıştırıldıktan sonra kaldırır ve zip dosyaları olduğu sürece devam eden bir bash 4 betiği. Bir alt dizindeki bir zip dosyası o alt dizine göre çıkarılır. Uyarı: denenmemişse, denemeden önce orijinal dosyaları yedekleyin veya rmzip dosyasını dizin ağacının dışına taşıyarak değiştirin .

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

shoptSatırı değiştirdiğinizde komut dosyası da zsh biçiminde çalışır setopt nullglob.

İşte taşınabilir bir eşdeğeri. Sonlandırma koşulu biraz karmaşıktır, çünkü findherhangi bir dosya bulup bulmadığını kendiliğinden döndürmez. Uyarı: yukarıdaki gibi.

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

unzipbunu yapmaz, çünkü UNIX yolu bir şeyi yapmak ve bunu iyi yapmaktır, her araçtaki tüm çılgın özel durumları ele almamaktır. Bu nedenle, kabuğu kullanmanız gerekir (bu da "şeyleri birbirine bağlamak" işini iyi yapar). Bu bir programlama sorusu yapar ve StackOverflow'da TÜM olası programlama soruları yanıtlandığından, burada: Bir dizindeki ve alt dizinlerindeki arşivleri Unix komut satırından yinelemeli olarak nasıl açabilirsiniz ?


1
Kesinlikle "kabuğu kullanarak" bir programlama sorusu çağırmaz ve "kabuk komut dosyası" SSS'de konu olarak listelenir
Michael Mrozek

Burada konu dışı olduğunu ima etmek için anlamsızdım, sadece neden StackOverflow'da konu üzerinde olduğunu gerekçelendirmek istedim.
Thomas Themel

1

Bu perl betiği her bir .zip dosyasını kendi alt dizinine ayıklayacaktır. İç içe geçmiş zip dosyalarını işlemek için komut dosyasını birden çok kez çalıştırın. Ayıklandıktan sonra .zip dosyalarını silmez, ancak bir unlink () çağrısı ekleyerek bu değişikliği yapabilirsiniz.

#!/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

En kolay yol atool kullanmaktır: http://www.nongnu.org/atool/ Herhangi bir arşivi çıkarmak için zip, unzip, katran, rar vb. Programları kullanan çok iyi bir betiktir .

Kullan atool -x package_name.ziphepsini halletmek veya birçok zip dosyaları ile dizine kullanmak istiyorsanız basit kullanmak fordöngü:

for f in *; do atool -x $f; fi(bunu cdkullanmadan önce zip dosyalarıyla istediğiniz dizine girmeniz gerekir).


atoolBuradaki davranışı unzip'ten önemli ölçüde farklı değil diyebilirim, ZIP dosyalarını özyinelemeli olarak da çıkarmaz.
Thomas Themel

@Thomas Themel: ZIP dosyalarını tekrar tekrar çıkarmadığından emin misiniz? Targz deb.gz rahatça ayıklayabilirsiniz ama iç içe zip arşivleri ile test etmek için hiçbir zaman atm var: \

0

Zip dosyalarının içindeki zip dosyalarını otomatik olarak açarken dikkatli olmak istersiniz:

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

Çıktı olarak bir zip dosyası üreten, çıktı olarak bir zip dosyası vb. Üreten bir zip dosyası oluşturmak mümkündür. Yani, programı "unzip" sabit bir merhem olan bir zip dosyası yapabilirsiniz.

Ayrıca, "patlayabilir" zip dosyaları yapma insanlar hatırlıyorum gibi, çok küçük bir zip dosyası çoklu gigabayt çıktı için unzip olacaktır. Bu, sıkıştırma yönteminin bir yönüdür.


0

Belki bu yardımcı olacaktır (benim için çalıştı):

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

Klasör yapısını korumak, her şeyi üst düzey dizine açmak değil, 2010'dan beri Giles gibi bir çözüme ihtiyacım vardı. İşte üç satır eklendi / değişti onun üzerine benim almak:

#!/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

Java tabanlı bu yardımcı programa göz atın Yuvalanmış zip dosyaları için nzip atın . Yuvalanmış fermuarların çıkarılması ve sıkıştırılması aşağıdaki komutlar kullanılarak kolayca yapılabilir

java -jar nzip.jar -c list -s readme.zip

java -jar nzip.jar -c özü -s "C: \ project \ readme.zip" -t benioku

java -jar nzip.jar -c sıkıştır -s benioku -t "C: \ proje \ readme.zip"

PS. Ben yazarım ve hataları hızlı bir şekilde düzeltmekten mutluluk duyacağım.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.