Dağınık bir klasörde nasıl-unzip, de-tar -xvf - de-unarchive nasıl?


14

Genellikle, bir şeyleri arşivden çıkarırım, $ mkdir newFolder; $ mv *.zip newFolder; $ cd newFolder; $unzip *.zipancak bazen tembelleşirim ve sadece keyfi bir klasörde yaparım, $ unzip *.zipböylece zaman zaman diğer içeriklerle uğraşırım. Burada bazı yöntemleri listeleyeceğim - bazı arşiv sürümü kesinlikle crappy bayraklara sahipken, diğerleri daha spartan, ikincisi ile daha fazla ilgileniyorum.

Arşivden çıkarmanın bazı yolları, başkaları var mı?

  1. $ find . -anewer fileThatExistedBeforeUnarchieving -ok rm '{}' \;Zayıf yönler *.zipdirileri listelemesidir , bu nedenle -okbirçok *.zipmaçla yavaş , yavaş kullanmanız gerekir ve bir nedenden dolayı çıkarılan her şeye uymuyor gibi görünüyor.

  2. Çıkarılan dosyalar az miktarda, tek tek, yavaş, hantal ve hata eğilimli.

  3. $ unzip -l *.bsdArşiv içeriğinin gerçekten bir klasör olup olmadığından emin olmak istediğimde, bazen kontrol ediyorum , en azından obsd'in unzip versiyonunda çalışıyor.

Belirli arşivleme araçlarına atıfta bulunuyorsanız, lütfen bunları uygun durumlarda belirtin. Yine de basit tutun - WAYS ile tek bir araç yerine nasıl yaptığınızı daha fazla merak ediyorum.



İşte mkdir; unzipşeyleri otomatikleştirmek için kullandığım bir komut dosyası, bu yüzden bunu yapmak için asla tembel değilim! svn.mikelward.com/svn/scripts/untar
Mikel

2
Bu ilgili soru ve cevaplara bakın: unix.stackexchange.com/questions/5123/…
alex

Yanıtlar:


11

İsimle

Arşivdeki dosyaların listesini oluşturabilir ve silebilirsiniz, ancak bu, unzip veya 7z gibi düz bir dosya adları listesi oluşturma seçeneği olmayan arşivlerle rahatsız edici bir şekilde hareket eder. Katranla bile, bu dosya adlarında yeni satır bulunmadığını varsayar.

tar tf foo.tar | while read -r file; do rm -- "$file" done
unzip -l foo.zip | awk '
    p && /^ --/ {p=2}
    p==1 {print substr($0, 29)}
    /^ --/ {++p}
' | while …
unzip -l foo.zip | tail -n +4 | head -n -2 | while …  # GNU coreutils only
7z l -slt foo.zip | sed -n 's/^Path = //p' | while …  # works on tar.*, zip, 7z and more

Dosyaları kaldırmak yerine, hedeflenen hedeflerine taşıyabilirsiniz.

tar tf foo.tar | while read -r file; do
  if [ -d "$file" ]; then continue; fi
  mkdir -p "/intended/destination/${file%/*}"
  mv -- "$file" "/intended/destination/$file"
done

FUSE ürününü kullanma

Harici araçlara bağlı kalmak yerine, (çoğu unice üzerinde) FUSE ürününü , normal dosya sistemi komutlarını kullanarak arşivleri işlemek için kullanabilirsiniz .

Bir zip içine bakmak, çıkartmak , içeriğini listelemek vb. İçin Fuse-zip kullanabilirsiniz .cpfind

mkdir /tmp/foo.d
fuse-zip foo.zip /tmp/foo.d
## Remove the files that were extracted mistakenly (GNU/BSD find)
(cd /tmp/foo.d && find . \! -type d -print0) | xargs -0 rm
## Remove the files that were extracted mistakenly (zsh)
rm /tmp/foo.d/**(:"s~/tmp/foo.d/~~"^/)
## Extract the contents where you really want them
cp -Rp /tmp/foo.d /intended/destination
fusermount -u foo.d
rmdir foo.d

AVFS , tüm arşiv hiyerarşinizin tüm arşivinin, içerik içeriğini tuttuğu görünen ilişkili bir dizine (sonunda # tacked ile aynı ad) sahip olduğu bir görünüm oluşturur.

mountavfs
## Remove the files that were extracted mistakenly (GNU/BSD find)
(cd ~/.avfs/"$PWD/foo.zip#" && find . \! -type d -print0) | xargs -0 rm
## Remove the files that were extracted mistakenly (zsh)
rm ~/.avfs/$PWD/foo.zip\#/**/*(:"s~$HOME/.avfs/$PWD/foo.zip#~~"^/)
## Extract the contents where you really want them
cp -Rp ~/.avfs/"$PWD/foo.zip#" /intended/destination
umountavfs

Tarihe göre

Senin çıkarma ile aynı hiyerarşi içinde herhangi etkinlik diğer olmamıştır varsayarsak, onların son tarafından çıkartılan dosyaları söyleyebilir ctime . Zip dosyasını yeni oluşturduysanız veya taşıdıysanız, bir kesme olarak kullanabilirsiniz; aksi takdirde ls -lctruygun bir kesme süresi belirlemek için kullanın . Fermuarları çıkarmamaya dikkat etmek istiyorsanız, herhangi bir manuel onay yapmak için hiçbir neden yoktur: findbunları hariç tutabilme özelliği mükemmeldir. Burada zsh veya find; o notu -cminve -cnewerön seçimler POSIX'deki değil ama Linux (ve GNU Bul ile diğer sistemlerde) mevcut, * BSD ve OSX.

find . \! -name '*.zip' -type f -cmin -5 -exec rm {} +  # extracted <5 min ago
rm **/*~*.zip(.cm-6)  # zsh, extracted ≤5 min ago
find . -type f -cnewer foo.zip -exec rm {} +  # created or moved after foo.zip

GNU find, FreeBSD ve OSX ile, kesme zamanını belirtmenin başka bir yolu bir dosya oluşturmak touchve mtime'ı kesme zamanına ayarlamak için kullanmaktır .

touch -d … cutoff
find . -type f -newercm cutoff -delete

Dosyaları kaldırmak yerine, hedeflenen hedeflerine taşıyabilirsiniz. İşte GNU / * BSD / OSX find ile hedefe gerektiği gibi dizinler oluşturarak bir yol.

find . \! -name . -cmin -5 -type f -exec sh -c '
    for x; do
      mkdir -p "$0/${x%/*}"
      mv "$x" "$0/$x"
    done
  ' /intended/destination {} +

Zsh eşdeğeri (neredeyse: bu, yalnızca dosya içerecek dizinleri değil, tüm dizin hiyerarşisini üretir):

autoload zmv
mkdir -p ./**/*(/cm-3:s"|.|/intended/destination|")
zmv -Q '(**/)(*)(.cm-3)' /intended/destination/'$1$2'

Uyarı, bu cevaptaki komutların çoğunu test etmedim. Kaldırmadan önce her zaman dosya listesini gözden geçirin (önce çalıştır echo, sonra sorun rmyoksa).


Sonunda bugün bu problemle karşılaştım. Kök olarak! Sonunda "İsme göre" ve "Tarihe göre" bir arada kullandım
phunehehe

1

Kendimi aptal hissediyorum, yine de benzer bir sorun yaşadığımda bu senaryoyu yazmak için başımı kaşıdım. Kullandığım cpioile -itdosyaların bir listesini almak için bayrak; diğer arşivleyiciler için eşdeğer komutları kullanabilirsiniz. Zor kısmı, cpio arşivi bir initrd'den ve içine çıkarıldım /, bu yüzden birçok klasör ve dosya çalışan bir sistemle aynı ada sahip. Neyse ki cpio mevcut dosyalarımın üzerine yazmadı. Yanlış komuttan önce var olan hiçbir şeyi silmemek için zaman kontrolü kullanıyorum.

#! /bin/sh

files=$(cpio -it < /mnt/temp/lglive.cpio)

for i in ${files}
do
    name=$(stat -c "%n" ${i})
    time=$(stat -c "%Y" ${i})
    # Time of the creation of the mess: 1296457595
    if [[ ${time} -gt 1296457590 && ${time} -lt 1296457600 ]]
    then
        if [[ -f ${name} ]]
        # If it is a file, it must have been created as part of the mess.
        then
            echo "rm ${name}"
        elif [[ -d ${name} ]]
        # If it is a directory, it may have been part of the mess
        # or maybe some files underneath it is created as part of the mess.
        then
            if [[ $(ls -A ${name}) ]]
            # If the directory contains something then don't delete it.
            then
                echo "${name} is not empty"
            # If the directory is empty then assume it is rubbish.
            else
                echo "rmdir ${name}"
            fi
        fi
    fi
done

echo "Files and directories still exist after the removal:"
for i in ${files}
do
    if [[ -e ${i} ]]
    then
        echo ${i}
    fi
done

0

Arşivdeki dosya listesini beslemeye ne dersiniz xargs rm?

Öyle tar -tf tarbomb.tar | xargs rmya da unzip --list zipbomb.zip | xargs rm.


2
Verilen komutlar genel durumda çalışmaz ve dosyaları kaldırdığınız için bu tehlikelidir . xargsgirdisinin kendine özgü olmayan bir şekilde alıntılanmasını bekler find. Kullanım xargs -I rm {}Xargs yerine her satıra bir öğe işler o kadar. Unzip komutu için hangi uygulamaya sahipsiniz? Mine (Debian / Ubuntu) --listsadece -lsahip değildir ve sadece dosya adlarını yazdırmaz, bu nedenle ekstra işlem gereklidir.
Gilles 'SO- kötü olmayı bırak'

@Gilles: 1) evet, tehlikeli, ama orijinal dosyaların üzerine yazdığımız için - zaten yoklar. 2) Bahsetmiyordum find. 3) Haklısın unzip, test etmedim ve dekore edilmemiş listeleme için seçenek yok gibi görünüyor. --listUbuntu'mda da hayır - sadece test etmedim.
alex

Hazır yanıt tar -tiçin özür dilerim find. Ama diğer noktalarım ayakta duruyor. Verilen komutunuzun alakasız bir dosyayı silme riski vardır.
Gilles 'SO- kötü olmayı kes

tar -tf tarbomb.tardosya adlarını her satıra bir tane yazdırır, böylece bunu yapabilir tar -tf tarbomb.tar | while IFS=$'\n' read -r filename; do rm "$filename"; doneveya benzeri yapabilirsiniz.
Mikel

0

Gerçekten ne istediğini değil, yerine bir "tümünü unzip" komut dosyası kullanmak nasıl.

unzip *.zip

Bu şekilde her dosyadan çıktı kendi dizinine girer.

#!/bin/bash
for f in *.zip ; do unzip -n "$f" -d "${f/%zip/out}"; done

0

Ben zsh aşağıdaki işlevi kullanın:

ununzip () {
    rm -r $(unzip -l $1 | grep -v 'Archive:' | \
    grep '[/.]' | sed 's![^a-zA-Z]([a-zA-Z./])!\1!')
}

Ie komut değiştirilen temizlenmiş çıktı tüm dosyaları kaldırmak için unzip -l.

tar tvf benzer bir şekilde kullanılabilir.

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.