Jak rozpakować, de-tar -xvf - cofnąć archiwizację w niechlujnym folderze?


14

Zwykle archiwizuję różne rzeczy, $ mkdir newFolder; $ mv *.zip newFolder; $ cd newFolder; $unzip *.zipale czasami leniwie i po prostu robię to w dowolnym folderze, $ unzip *.zipwięc od czasu do czasu mam problemy z innymi treściami. Wymienię tutaj niektóre metody - niektóre wersje archiwalne z pewnością mają gówniane flagi, podczas gdy inne są bardziej spartańskie, bardziej interesuje mnie ta ostatnia.

Niektóre sposoby na wyłączenie archiwizacji, czy są jeszcze inne?

  1. $ find . -anewer fileThatExistedBeforeUnarchieving -ok rm '{}' \;Słabości polegają na tym, że zawiera listę *.zipreżimów, więc musisz używać powolnego -ok, powolnego z wieloma *.zipdopasowaniami, a z jakiegoś powodu nie wydaje się pasować do wszystkich wyodrębnionych.

  2. Jeśli niewielka ilość wyodrębnionych plików, jeden po drugim, powolny, uciążliwy i podatny na błędy.

  3. Kiedy chcę się upewnić, czy zawartość archiwum jest rzeczywiście folderem, czasami sprawdzam $ unzip -l *.bsd, czy działa, przynajmniej w wersji undip obsda.

Jeśli masz na myśli niektóre narzędzia do archiwizacji, podaj je w razie potrzeby. Uprość to - bardziej interesuje mnie SPOSOBY, w jaki sposób to robisz, niż pojedyncze narzędzie.



Oto skrypt, którego używam do automatyzacji mkdir; unziprzeczy, więc nigdy nie jestem zbyt leniwy, aby to zrobić! svn.mikelward.com/svn/scripts/untar
Mikel

2
Zobacz to powiązane pytanie i odpowiedzi: unix.stackexchange.com/questions/5123/…
alex

Odpowiedzi:


11

Wg nazwy

Możesz wygenerować listę plików w archiwum i usunąć je, ale jest to denerwująco kłopotliwe w przypadku archiwizatorów takich jak unzip lub 7z, które nie mają opcji generowania prostej listy nazw plików. Nawet w przypadku tar, zakłada się, że w nazwach plików nie ma nowych linii.

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

Zamiast usuwać pliki, możesz przenieść je do miejsca docelowego.

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

Korzystanie z BEZPIECZNIKA

Zamiast polegać na narzędziach zewnętrznych, możesz (w większości jednorożców) używać FUSE do manipulowania archiwami przy użyciu zwykłych poleceń systemu plików.

Możesz użyć Fuse-zip, aby zajrzeć do pliku zip, wyodrębnić go cp, wyświetlić listę jego zawartości za pomocą finditp.

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

System AVFS tworzy widok całej hierarchii katalogów, w której wszystkie archiwa mają powiązany katalog (ta sama nazwa z # tacked na końcu), który wydaje się zawierać zawartość archiwum.

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

Według daty

Zakładając, że nie było żadnej innej aktywności w tej samej hierarchii niż ekstrakcja, możesz wyodrębnić pliki według ich ostatniej godziny . Jeśli właśnie utworzyłeś lub przeniosłeś plik zip, możesz użyć go jako odcięcia; w przeciwnym razie użyj, ls -lctraby ustalić odpowiedni czas odcięcia. Jeśli chcesz mieć pewność, że nie usuniesz zamków, nie ma powodu, aby dokonywać ręcznego zatwierdzania: findjest w stanie całkowicie je wykluczyć. Oto przykładowe polecenia używające zsh lub find; zauważ, że -cmini podstawowe -cnewernie są w POSIX, ale istnieją w Linux (i innych systemach z GNU find), * BSD i 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

W GNU find, FreeBSD i OSX, innym sposobem na określenie czasu odcięcia jest utworzenie pliku i użycie go touchdo ustawienia czasu mtime na czas odcięcia.

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

Zamiast usuwać pliki, możesz przenieść je do miejsca docelowego. Oto sposób wyszukiwania GNU / * BSD / OSX, tworząc katalogi w miejscu docelowym w razie potrzeby.

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

Odpowiednik Zsh (prawie: ten odtwarza całą hierarchię katalogów, nie tylko katalogi, które będą zawierać pliki):

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

Ostrzeżenie, nie testowałem większości poleceń w tej odpowiedzi. Zawsze sprawdzaj listę plików przed usunięciem ( echonajpierw uruchom , a następnie, rmjeśli jest w porządku).


W końcu dzisiaj mam ten problem. Jako root! W końcu użyłem kombinacji „Według nazwy” i „Według daty”
phunehehe 31.01.11

1

Czuję się głupio, w każdym razie podrapałem się w głowę, żeby napisać ten skrypt, gdy miałem podobny problem. Użyłem cpioz -itflagą, aby uzyskać listę plików; możesz użyć równoważnych poleceń dla innych archiwizatorów. Problem polega na tym, że archiwum cpio pochodzi z initrd i rozpakowałem je /, więc wiele folderów i plików ma taką samą nazwę jak w działającym systemie. Na szczęście cpio nie nadpisało żadnego z moich istniejących plików. Używam sprawdzania czasu, aby upewnić się, że nie usuwam niczego, co istniało przed złym poleceniem.

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

Co powiesz na karmienie listy plików w archiwum xargs rm ?

To byłoby tar -tf tarbomb.tar | xargs rmlub unzip --list zipbomb.zip | xargs rm.


2
Podane polecenia nie będą działać w ogólnym przypadku, a to jest niebezpieczne, ponieważ usuwasz pliki. xargsoczekuje, że dane wejściowe zostaną podane w szczególny sposób, findale nie przyniosą rezultatu. Użyj xargs -I rm {}, aby xargs zamiast tego przetwarzał jeden element w wierszu. Jaką masz implementację polecenia unzip? Mój (Debian / Ubuntu) nie ma --list, tylko -l, i nie tylko drukuje nazwy plików, więc potrzebne jest dodatkowe przetwarzanie.
Gilles „SO- przestań być zły”

@Gilles: 1) tak, to niebezpieczne, ale ponieważ prawdopodobnie nadpisaliśmy oryginalne pliki - już ich nie ma. 2) Nie mówiłem find. 3) masz rację co do tego unzip, że nie testowałem i wydaje się, że nie ma opcji nieposiadającego wykazu. Nie --listna moim Ubuntu - po prostu nie testowałem.
alex

Przepraszamy za odpowiedź w puszce, zamień tar -tna find. Ale moje inne punkty są ważne. Istnieje realne ryzyko, że podane polecenie usunie niepowiązany plik.
Gilles „SO- przestań być zły”

tar -tf tarbomb.tarwypisze nazwy plików po jednym w wierszu, abyś mógł zrobić coś tar -tf tarbomb.tar | while IFS=$'\n' read -r filename; do rm "$filename"; donepodobnego.
Mikel

0

Nie do końca to, o co prosiłeś, ale może zamiast tego użyć skryptu „rozpakuj wszystko”.

unzip *.zip

W ten sposób dane wyjściowe z każdego pliku trafiają do własnego katalogu.

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

0

Używam następującej funkcji w zsh:

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

Tj. Podstawienie polecenia, aby usunąć wszystkie pliki z oczyszczonego wyjścia unzip -l .

tar tvf może być użyty w podobny sposób.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.