Jak rozpakować bezpiecznie, bez zanieczyszczania bieżącego katalogu w przypadku tarbomb?

33

Projekty szanowanych zwolnić archiwa tar, które zawierają pojedynczy katalog, na przykład zyrgus-3.18.tar.gzzawiera zyrgus-3.18folder, który z kolei zawiera src, build, dist, itd.

Ale w niektórych projektach punkowych wszystko leży u podstaw: „(powoduje to całkowity bałagan podczas rozpakowywania. Ręczne tworzenie folderu za każdym razem jest uciążliwe i niepotrzebne przez większość czasu.

  • Czy istnieje superszybki sposób stwierdzenia, czy plik .tar lub .tar.gz zawiera więcej niż jeden katalog w katalogu głównym? Nawet dla dużego archiwum.
  • Lub jeszcze lepiej, czy istnieje narzędzie, które w takich przypadkach stworzyłoby katalog (nazwę archiwum bez rozszerzenia) i umieściłoby wszystko w środku?
Nicolas Raoul
źródło
2
Myślę, że zepsute opakowanie jest warte zgłoszenia błędu autorowi pakietu.
14
Historycznie (od połowy lat 90.) po prostu zawsze rozpakowywałem się w podkatalogu. Jeśli wszystko jest umieszczone w jednym katalogu (tak, jak powinno być), jego zawartość można następnie przenieść za pomocą mv we właściwe miejsce, a następnie można usunąć zbędny dodatkowy katalog. Dwa dodatkowe kroki tak, ale pokonuje usuwanie bałaganu z błędnie utworzonego pliku tar.
TED,
6
But some punk projects put everything at the root :'-(Niektóre projekty punkowe całkowicie niepotrzebnie umieszczają wszystko w folderze, biorąc pod uwagę, że umieszczają już wszystko w załączonym archiwum, więc kiedy pobierzesz i rozpakujesz go do własnego folderu, tak jak zrobiłby to każdy inteligentny użytkownik, skończysz z całą treść zakryła kolejną warstwę. ;-)
Mason Wheeler
2
@MasonWheeler Istnieje pewien „de facto standard” dla archiwów tar, aby mieć wszystko w jednym folderze.
glglgl,

Odpowiedzi:

30

patool obsługuje różnego rodzaju archiwa i tworzy podkatalog na wypadek, gdyby archiwum zawierało wiele plików, aby zapobiec zaśmiecaniu katalogu roboczego wyodrębnionymi plikami.

Wyodrębnij archiwum

patool extract archive.tar

Aby uzyskać listę obsługiwanych formatów, użyj patool formats.

Marco
źródło
FYI: Znaleziono go na sourceforge.net/projects/patool . Jest to rpm i kiedyś alienkonwertowałem go na deb dla Ubuntu.
Joe
patoolpowinien być w repozytoriach dla Debiana i Ubuntu, jeśli używasz aktualnej wersji.
Marco
12

Możesz zrobić coś takiego

tar tf thefile.tar | cut -d/ -f1 | sort -u

aby zobaczyć, jakie wpisy najwyższego poziomu mają tar; potokuj, aby wc -lsprawdzić, czy jest więcej niż jeden. Zauważ, że jest kilka przypadków, w których to się nie powiedzie, np. Jeśli tar zawiera ścieżki plików formularza somedir/whateveri również ./somedir/whatever(lub coś bardziej szalonego); powinno to jednak być rzadkie.

Spowoduje to odczytanie całego pliku tar przed wypisaniem czegokolwiek, ponieważ sortpowinno to być szybsze niż rozpakowywanie, ponieważ jest to tylko jeden odczyt sekwencyjny i może pomijać duże pliki.

Jeśli robisz to interaktywnie, a plik może być duża, można zmienić sort -udo uniqi Control+ Cjeśli drukuje się więcej niż jedno.

Dougal
źródło
2
sort | uniqmożna skrócić do sort -u.
Marco
4
chyba że chcesz to zrobićuniq -c
cas
7

możesz to zrobić:

pax <some.tar

... aby wyświetlić zawartość tarpliku.

jeśli chcesz wiedzieć, ile to poziomów, możesz zrobić:

pax <some.tar | tr -dc /\\n | sort -r | head -n1

możesz jawnie zabronić eksplozji podczas ekstrakcji za pomocą:

mkdir some.tar
pax -'rs|^|some.tar/|' <some.tar
mikeserv
źródło
2

To powinno zrobić, co chcesz. Jestem pewien, że ktoś może to poprawić. W tych przykładach zakładam, że archiwum tar skompresowane gzip jest najczęstsze.

Chcesz archiwum, w którym nie ma węzłów rodzeństwa w drzewie katalogów na poziomie katalogu głównego.

Każdy wpis na liście zawartości tar musi zaczynać się od tego samego wzorca. Ten wzorzec jest ścieżką katalogu podstawowego, którą muszą udostępniać wszystkie wpisy w archiwum. Jeśli jakieś dwa wpisy nie zaczynają się od tego samego wzorca, są rodzeństwem.

Pierwszy wiersz na liście zawartości tar podaje minimalny wzorzec, który należy sprawdzić. To jest BASEPATH.

BASEPATH=$(tar ztf example.tar.gz | (read line; echo $line))

Następnie do testu dla tarballs wybuchem trzeba sprawdzić, czy każdy wiersz listy zawartości smoły nie zacząć od BasePath.

tar ztf example.tar.gz | grep -qv "^${BASEPATH}"

Zmień to w funkcję powłoki:

is_explosive() {
    TARBALL_NAME=$1
    tar ztf "${TARBALL_NAME}" | grep -qv "^$(tar ztf "${TARBALL_NAME}" | (read line; echo ${line}))"
    return $?
}

Stąd możesz napisać bezpieczną funkcję ekstrakcji archiwum tar.

is_explosive() {
    TARBALL_NAME=$1
    tar ztf "${TARBALL_NAME}" | grep -qv "^$(tar ztf "${TARBALL_NAME}" | (read line; echo ${line}))"
    return $?
}

safe_tar_x() {
    TARBALL_NAME=$1
    if is_explosive ${TARBALL_NAME}; then
        SUBDIR=${TARBALL_NAME%.tar.gz}
        SUBDIR=${SUBDIR##*/}
        mkdir "${SUBDIR}"
        echo "WARNING: This tarball is explosive. Opening in subdirectory, ${SUBDIR}, for safety." >&2
    else
        SUBDIR="."
    fi
    # Tar quirks: "--directory" must be last, and using more than
    #     one option group requires that all groups start with a dash.
    tar -zxf "${TARBALL_NAME}" --directory "${SUBDIR}"
    return $?
}
Noah Spurrier
źródło