2008-09-20 16 views
43

unzip komutunda, arşivlerin ardışık olarak çıkarılması için bir seçenek yoktur.Bir dizinde ve alt dizinlerinde bulunan arşivleri Unix komut satırından nasıl yinelemeli olarak ayıklarsınız?

ise aşağıdaki dizin yapısı ve arşivleri vardır:

 
/Mother/Loving.zip 
/Scurvy/Sea Dogs.zip 
/Scurvy/Cures/Limes.zip 

Ve her arşivde aynı ada sahip dizinlere arşivlerinin tüm halletmek istiyorum:

 
/Mother/Loving/1.txt 
/Mother/Loving.zip 
/Scurvy/Sea Dogs/2.txt 
/Scurvy/Sea Dogs.zip 
/Scurvy/Cures/Limes/3.txt 
/Scurvy/Cures/Limes.zip 

Ne komutu veya komutları verir miydim?

Bu, içinde boşluk bulunan dosya adlarını tıkamadığından önemlidir. -r bayrağını kullanarak gunzip'in gibi

find . -name "*.zip" | while read filename; do unzip -o -d "`basename -s .zip "$filename"`" "$filename"; done; 
+0

Uzun dosya yollarına ne dersin ... 260 karakterin ötesine ...: https://superuser.com/a/1263234/439537 – Andrew

cevap

59

Eğer ilgili klasöre ayıklamak istiyorsanız yüksek işleyebilir sistemler için bu

find . -name "*.zip" | while read filename; do unzip -o -d "`dirname "$filename"`" "$filename"; done; 

bir çok işlenmiş versiyonunu G/Ç deneyebilirsiniz:

find . -name "*.zip" | xargs -P 5 -I fileName sh -c 'unzip -o -d "$(dirname "fileName")/$(basename -s .zip "fileName")" "fileName"' 
+1

Tam dizini koruduğu için bunu yapmanın doğru yolu budur. Yapı! – kynan

+2

__NOTE__ - bu dosyalar arşivle aynı adı taşıyan dizinlere istendiği gibi çıkarılmıyor – emlai

+0

Xargs'ın çok çekirdekli desteği olduğu konusunda hiçbir fikrim yoktu! – chuckrector

29

İşte bulmak komuta ve bir süre döngü gerektirir bir çözümdür. Komut satırında belirtilen dosya adlarından herhangi biri dizinse, gzip dizine iner ve orada bulduğu tüm dosyaları sıkıştırır (veya gunzip durumunda sıkıştırır).

, sözdizimi İşlevi biraz farklı

http://www.computerhope.com/unix/gzip.htm

+3

** NOT ** - bu, tüm zip dosyalarını ** çalışma dizinine ayıklar. ! ** göreceli bir unzip talep ederken. [Vivek'in cevabı] 'na bakın (http://stackoverflow.com/a/2318189/3191896) –

+0

Hmm, bunların tümünü AFAICT çalışma dizinine ayıklamıyor. OS X El Capitan 10.11.6'dan UnZip 5.52 kullanıyorum. Sonuçlar Vivek'inkiyle aynı görünmektedir. Cevabını kabul ederek, aynı zamanda birden fazla çekirdekten nasıl yararlanabileceğinizi de gösterir! – chuckrector

2

şey ....

Seyahat dizin yapısı yinelemeli:?

+2

Özellikle zip dosyaları hakkında konuşuyor, gzip dosyaları değil. – dvorak

4

Sen

find . -name "*.zip" -exec unzip {} \; 
+0

Bu, her alt dizine göre değil, her şeyi geçerli dizine ayıklar. Ayrıca, her arşivle aynı ada sahip bir dizinde unzip olmaz. – chuckrector

+0

-d hakkının alınmasının okuyucu için bir egzersiz olarak bırakıldığını varsayalım. Bu okuyucunun -exec'in sadece bir komutta {} kullanımına izin verdiğine dikkat etmeliyiz - bir değişkeni sh çağırıp {} atayarak bunu aşın. –

+0

Ayrıca -execdir bazen -exec tercih edilir olduğunu unutmayın. Bu durumda bunun önemli olacağını düşünmüyorum. –

0

cygwin kullanıyorsanız işi yapmak için tek komut satırında -exec bayrağı ile birlikte bulmak kullanabilirsiniz olduğu komut.

find . -name "*.zip" | while read filename; do unzip -o -d "`basename "$filename" .zip`" "$filename"; done; 
0

Bunun çok eski olduğunu anlıyorum, ancak benzer bir şeye benzer bir çözüm aradığımda Google’daki ilk isabetler arasındaydı, bu yüzden burada yaptığım şeyi yayınlayacağım. Benim senaryo Esasen sadece tamamen bunun içindeki bütün kavanozlar ile birlikte bir kavanoz patlamaya istediği gibi biraz farklıdır, bu yüzden aşağıdaki bash fonksiyonları yazdı:

function explode { 
    local target="$1" 
    echo "Exploding $target." 
    if [ -f "$target" ] ; then 
     explodeFile "$target" 
    elif [ -d "$target" ] ; then 
     while [ "$(find "$target" -type f -regextype posix-egrep -iregex ".*\.(zip|jar|ear|war|sar)")" != "" ] ; do 
      find "$target" -type f -regextype posix-egrep -iregex ".*\.(zip|jar|ear|war|sar)" -exec bash -c 'source "<file-where-this-function-is-stored>" ; explode "{}"' \; 
     done 
    else 
     echo "Could not find $target." 
    fi 
} 

function explodeFile { 
    local target="$1" 
    echo "Exploding file $target." 
    mv "$target" "$target.tmp" 
    unzip -q "$target.tmp" -d "$target" 
    rm "$target.tmp" 
} 

Not depoladığınız eğer ihtiyaç vardır <file-where-this-function-is-stored> Bu, olmadığım gibi etkileşimli olmayan bir kabuk için okunmayan bir dosyada. İşlevleri, etkileşimli olmayan kabuklara yüklenen bir dosyada (örneğin, .bashrc inanıyorum) depolıyorsanız, source ifadesinin tamamını bırakabilirsiniz. Umarım bu birisine yardım eder.

Küçük bir uyarı - explodeFile ayrıca fermuarlı dosyayı siler, tabii ki son satırı yorumlayarak değiştirebilirsiniz.

10

doğru sadece kaldırıldı uzantılı, (satırbaşıyla dahil) tüm dosya adlarını kolları ve dosyasıyla aynı konumda olan bir dizine ayıklar bir çözüm:

find . -name '*.zip' -exec sh -c 'unzip -o -d "${0%.*}" "$0"' '{}' ';' 

Not kolayca yapabilirsiniz

find . '(' -name '*.zip' -o -name '*.jar' ')' -exec ... 
0

başka ilginç çözüm olacaktır:

o örn -o kullanarak ekleyerek daha fazla dosya türlerini (örneğin .jar gibi) ele 0
DESTINY=[Give the output that you intend] 

# Don't forget to change from .ZIP to .zip. 
# In my case the files were in .ZIP. 
# The echo were for debug purpose. 

find . -name "*.ZIP" | while read filename; do 
ADDRESS=$filename 
#echo "Address: $ADDRESS" 
BASENAME=`basename $filename .ZIP` 
#echo "Basename: $BASENAME" 
unzip -d "$DESTINY$BASENAME" "$ADDRESS"; 
done; 
İlgili konular