Как распаковать безопасно, не загрязняя текущий каталог в случае tarbomb?


33

Солидные проекты освободить архивы дегтя, содержащие один каталог, например , zyrgus-3.18.tar.gzсодержит zyrgus-3.18папку , которая , в свою очередь , содержит src, build, distи т.д.

Но некоторые панк-проекты помещают все в корень: '- (Это приводит к полному беспорядку при разархивировании. Создание папки каждый раз вручную - это боль и ненужная большая часть времени.

  • Существует ли сверхбыстрый способ определить, содержит ли файл .tar или .tar.gz несколько корневых каталогов? Даже для большого архива.
  • Или даже лучше, есть ли инструмент, который в таких случаях будет создавать каталог (имя архива без расширения) и помещать все внутри?


2
Я думаю, что сломанная упаковка стоит сообщения об ошибке автору пакета.

14
Я исторически (с середины 90-х) просто всегда оставался в подкаталоге. Если все это поместить в один каталог (как и должно быть), его содержимое затем можно переместить в нужное место с помощью mv, тогда вы можете удалить лишний дополнительный каталог. Да, два дополнительных шага, но это лучше, чем убирать беспорядок из неправильно созданного файла tar.
TED

6
But some punk projects put everything at the root :'-(И некоторые панк-проекты совершенно бесполезно помещают все в папку, учитывая, что они уже помещают все в прилагаемый архив, поэтому, когда вы загружаете и распаковываете его в свою собственную папку, как это делал бы любой умный пользователь, вы в конечном итоге получаете все содержание похоронило еще один слой вниз. ;-)
Мейсон Уилер

2
@MasonWheeler Для архивов tar существует своего рода «стандарт де-факто», в котором все находится внутри одной папки.
glglgl

Ответы:


30

patool обрабатывает различные виды архивов и создает подкаталог на тот случай, если архив содержит несколько файлов, чтобы не загромождать рабочий каталог извлеченными файлами.

Извлечь архив

patool extract archive.tar

Чтобы получить список поддерживаемых форматов, используйте patool formats.


К вашему сведению: нашел его на sourceforge.net/projects/patool . Это rpm, и я alienконвертировал его в deb для Ubuntu.
Джо

patoolдолжен быть в репозиториях для Debian и Ubuntu, если вы используете текущую версию.
Марко

12

Вы могли бы сделать что-то вроде

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

посмотреть, какие записи верхнего уровня есть у tar; труба, чтобы wc -lпроверить, если есть больше чем один. Обратите внимание, что есть несколько случаев, когда это может не сработать, например, если tar содержит пути к файлам формы, somedir/whateverа также ./somedir/whatever(или что-то более безумное); это должно быть необычным, хотя.

Это прочитает весь tar-файл перед выводом чего-либо, потому что sort, хотя это должно быть быстрее, чем на самом деле извлечение, потому что это только одно последовательное чтение, и оно может пропускать большие файлы.

Если вы делаете это в интерактивном режиме, и файл может быть большим, вы можете изменить sort -uк uniqи Control+ Cесли он печатает более чем одну вещь.


2
sort | uniqможно сократить до sort -u.
Марко

4
если вы не хотите делатьuniq -c
cas

7

ты можешь сделать:

pax <some.tar

... для просмотра содержимого tarфайла.

если вы хотите узнать, сколько уровней он проходит, вы можете сделать:

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

Вы можете явно запретить взрыв при извлечении с помощью:

mkdir some.tar
pax -'rs|^|some.tar/|' <some.tar

2

Это должно делать то, что вы хотите. Я уверен, что кто-то может улучшить это. В этих примерах я предполагаю сжатый архивом gzip tar, поскольку он является наиболее распространенным.

Вы хотите архив, в котором нет дочерних узлов в дереве каталогов корневого уровня.

Каждая запись в списке содержимого tar должна начинаться с одного и того же шаблона. Этот шаблон является базовым путем к каталогу, который должны совместно использоваться всеми записями в архиве. Если любые две записи не начинаются с одного и того же шаблона, то они являются братьями и сестрами.

Первая строка в списке содержимого tar предоставит вам минимальный шаблон, который вы должны проверить. Это BASEPATH.

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

Затем, чтобы проверить наличие взрывоопасных тарболов, вам нужно проверить , не начинается ли какая-либо строка списка содержимого tar с BASEPATH.

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

Преврати это в функцию оболочки:

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

Отсюда вы можете написать безопасную функцию извлечения архива 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 $?
}

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.