Como descompactar com segurança, sem poluir o diretório atual em caso de um tarbomb?

33

Projetos respeitáveis liberar arquivos tar que contêm um único diretório, por exemplo zyrgus-3.18.tar.gzcontém uma zyrgus-3.18pasta que por sua vez contém src, build, dist, etc.

Mas alguns projetos punk colocam tudo na raiz: '- (Isso resulta em uma bagunça total ao desarquivar. Criar uma pasta manualmente toda vez é doloroso e desnecessário na maioria das vezes.

  • Existe uma maneira super rápida de saber se um arquivo .tar ou .tar.gz contém mais de um diretório único em sua raiz? Mesmo para um grande arquivo.
  • Ou melhor ainda, existe uma ferramenta que, nesses casos, criaria um diretório (nome do arquivo sem a extensão) e colocaria tudo dentro?
Nicolas Raoul
fonte
2
Acho que embalagens quebradas valem um relatório de bug para o autor do pacote.
14
Historicamente (desde meados dos anos 90), sempre desdentado em um subdiretório. Se tudo estiver em um único diretório (como deveria ser), seu conteúdo poderá ser movido para o lugar certo com mv, e você poderá excluir o diretório extra supérfluo. Duas etapas extras, sim, mas é melhor do que limpar a bagunça de um arquivo tar incorreto.
TED
6
But some punk projects put everything at the root :'-(E alguns projetos punk colocam tudo dentro de uma pasta completamente desnecessariamente, considerando que eles já estão colocando tudo dentro de um arquivo anexo, de modo que, quando você o baixa e descompacta em uma pasta própria, como qualquer usuário inteligente faria, você acaba com todos os conteúdo enterrado outra camada abaixo. ;-)
Mason Wheeler
2
@MasonWheeler Existe um tipo de "padrão de fato" para que os arquivos tar possuam tudo em uma pasta.
glglgl

Respostas:

30

O patool lida com diferentes tipos de arquivos e cria um subdiretório, caso o arquivo contenha vários arquivos para evitar a confusão do diretório de trabalho com os arquivos extraídos.

Extrair arquivo

patool extract archive.tar

Para obter uma lista dos formatos suportados, use patool formats.

Marco
fonte
FYI: Encontrei em sourceforge.net/projects/patool . É um rpm e eu costumava alienconvertê-lo em um deb para o Ubuntu.
9135 Joe
patooldeve estar nos repositórios para Debian e Ubuntu se você estiver executando uma versão atual.
Marco
12

Você poderia fazer algo como

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

para ver quais entradas de nível superior um alcatrão possui; canalize para wc -lverificar se há mais de um. Observe que existem alguns casos em que isso falhará, por exemplo, se o tar contiver caminhos de arquivo do formulário somedir/whatevere também ./somedir/whatever(ou algo mais louco); isso deve ser incomum, no entanto.

Isso lerá o arquivo tar inteiro antes de produzir qualquer coisa, por causa do sort, embora deva ser mais rápido do que realmente extrair, porque é apenas uma leitura seqüencial e pode pular arquivos grandes.

Se você estiver fazendo isso de maneira interativa e o arquivo puder ser grande, poderá alterar sort -upara uniqe Control+ Cse imprimir mais de uma coisa.

Dougal
fonte
2
sort | uniqpode ser reduzido para sort -u.
Marco
4
a menos que você queira fazeruniq -c
cas
7

você pode fazer:

pax <some.tar

... para listar o conteúdo de um tararquivo.

se você quiser saber quantos níveis de profundidade existem, você pode:

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

você pode proibir explicitamente uma explosão na extração com:

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

Isso deve fazer o que você quiser. Tenho certeza que alguém pode melhorá-lo. Nestes exemplos, assumo um arquivo tar compactado gzip, já que este é o mais comum.

Você deseja um archive em que não haja nós irmãos na árvore de diretórios no nível raiz.

Cada entrada na lista de conteúdo tar deve começar com o mesmo padrão. Esse padrão é o caminho do diretório base que todas as entradas no arquivo morto devem compartilhar. Se duas entradas não começarem com o mesmo padrão, elas serão irmãos.

A primeira linha na lista de conteúdo tar fornecerá o padrão mínimo que você precisa verificar. Este é o BASEPATH.

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

Então, para teste de tarballs explosivos que você precisa verificar se qualquer linha da lista de teor de alcatrão não começar com o BasePath.

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

Transforme isso em uma função shell:

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

A partir daqui, você pode escrever uma função segura de extração de arquivos 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
fonte