¿Cómo descomprimir de forma segura, sin contaminar el directorio actual en caso de una tarbomb?

33

Proyectos respetables liberan archivos de alquitrán que contienen un único directorio, por ejemplo, zyrgus-3.18.tar.gzcontiene una zyrgus-3.18carpeta que a su vez contiene src, build, dist, etc.

Pero algunos proyectos punk ponen todo en la raíz: '- (Esto resulta en un desorden total cuando se desarchiva. Crear una carpeta manualmente cada vez es un dolor e innecesario la mayor parte del tiempo.

  • ¿Hay una manera súper rápida de saber si un archivo .tar o .tar.gz contiene más de un directorio en su raíz? Incluso para un gran archivo.
  • O mejor aún, ¿existe una herramienta que en tales casos crearía un directorio (nombre del archivo sin la extensión) y pondría todo dentro?
Nicolas Raoul
fuente
2
Creo que el empaque roto vale un informe de error al autor del paquete.
14
Históricamente (desde mediados de los años 90) siempre me he separado de un subdirectorio. Si todo se coloca en un solo directorio (como debería ser), su contenido se puede mover al lugar correcto con mv, luego puede eliminar el directorio extra superfluo. Dos pasos adicionales sí, pero es mejor que limpiar el desastre de un archivo tar mal hecho.
TED
66
But some punk projects put everything at the root :'-(Y algunos proyectos punk colocan todo dentro de una carpeta completamente innecesariamente, considerando que ya están poniendo todo dentro de un archivo adjunto, de modo que cuando lo descarga y descomprime en su propia carpeta como lo haría cualquier usuario inteligente, termina con todos los contenido enterrado otra capa hacia abajo. ;-)
Mason Wheeler
2
@MasonWheeler Existe una especie de "estándar de facto" para que los archivos tar contengan todo en una carpeta.
glglgl

Respuestas:

30

patool maneja diferentes tipos de archivos y crea un subdirectorio en caso de que el archivo contenga múltiples archivos para evitar el desorden en el directorio de trabajo con los archivos extraídos.

Extraer archivo

patool extract archive.tar

Para obtener una lista de los formatos compatibles, use patool formats.

Marco
fuente
FYI: Lo encontré en sourceforge.net/projects/patool . Es un rpm y solía alienconvertirlo en un deb para Ubuntu.
Joe
patooldebería estar en los repositorios de Debian y Ubuntu si está ejecutando una versión actual.
Marco
12

Podrías hacer algo como

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

para ver qué entradas de nivel superior tiene un alquitrán; tubería para wc -lverificar si hay más de uno. Tenga en cuenta que hay algunos casos en los que esto podría fallar, por ejemplo, si el tar contiene rutas de archivo del formulario somedir/whatevery también ./somedir/whatever(o algo más loco); Sin embargo, esto debería ser poco común.

Esto leerá todo el archivo tar antes de generar algo, debido a que sort, aunque debería ser más rápido que extraerlo realmente porque es solo una lectura secuencial y puede omitir archivos grandes.

Si usted está haciendo esto de forma interactiva y el archivo puede ser grande, puede cambiar sort -ua uniqy Control+ Csi se imprime más de una cosa.

Dougal
fuente
2
sort | uniqse puede acortar a sort -u.
Marco
44
a menos que quieras hacerlouniq -c
cas
7

tu puedes hacer:

pax <some.tar

... para enumerar el contenido de un tararchivo.

si quieres saber cuántos niveles de profundidad tiene, puedes hacer:

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

puede prohibir explícitamente una explosión en la extracción con:

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

Esto debería hacer lo que quieras. Estoy seguro de que alguien puede mejorarlo. En estos ejemplos, supongo un archivo tar comprimido de gzip ya que este es el más común.

Desea un archivo donde no haya nodos hermanos en el árbol de directorios del nivel raíz.

Cada entrada en la lista de contenido de alquitrán debe comenzar con el mismo patrón. Este patrón es la ruta del directorio base que todas las entradas del archivo deben compartir. Si dos entradas cualesquiera no comienzan con el mismo patrón, entonces son hermanos.

La primera línea en la lista de contenido de alquitrán le dará el patrón mínimo que debe verificar. Esta es la BASEPATH.

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

A continuación, a prueba de bolas de alquitrán explosivos que necesita para comprobar si cualquier línea de la lista de contenido de alquitrán no comienzan con la BASEPATH.

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

Convierta esto en una función de shell:

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

Desde aquí puede escribir una función segura de extracción de archivos 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
fuente