¿Cómo descomprimir, des tar -xvf - desarchivar en una carpeta desordenada?

14

Por lo general, desarchivo las cosas, $ mkdir newFolder; $ mv *.zip newFolder; $ cd newFolder; $unzip *.zippero a veces me vuelvo vago y solo lo hago en una carpeta arbitraria, $ unzip *.zipasí que de vez en cuando me equivoco con otro contenido. Enumeraré aquí algunos métodos: algunas versiones de archivo seguramente tienen banderas malas, mientras que otras son más espartanas, estoy más interesado en lo último.

Algunas formas de desarchivar, ¿hay otras?

  1. $ find . -anewer fileThatExistedBeforeUnarchieving -ok rm '{}' \;Las debilidades son que enumera los *.zipdirectorios, por lo que debe usar slow -ok, slow con muchas *.zipcoincidencias y, por alguna razón, no parece coincidir con todo lo extraído.

  2. Si es una pequeña cantidad de archivos extraídos, uno por uno, lento, engorroso y propenso a errores.

  3. Cuando quiero asegurarme de si el contenido del archivo es realmente una carpeta, a veces lo compruebo $ unzip -l *.bsd, funciona al menos en la versión descomprimida de obsd.

Si se refiere a ciertas herramientas de archivo, indíquelas cuando corresponda. Sin embargo, manténgalo simple: estoy más interesado en la forma en que lo hace, en lugar de una sola herramienta.

Rui F Ribeiro
fuente
1
Consulte también Ubicación de extractos accidentales: ¿cómo limpiar?
Gilles 'SO- deja de ser malvado'
Aquí hay un script que uso para automatizar las mkdir; unzipcosas, ¡así que nunca soy demasiado flojo para hacerlo! svn.mikelward.com/svn/scripts/untar
Mikel
2
Vea esta pregunta y respuestas relacionadas: unix.stackexchange.com/questions/5123/…
alex

Respuestas:

11

Por nombre

Puede generar la lista de archivos en el archivo y eliminarlos, aunque esto es molestamente complicado con archivadores como descomprimir o 7z que no tienen una opción para generar una lista simple de nombres de archivo. Incluso con alquitrán, esto supone que no hay nuevas líneas en los nombres de archivo.

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

En lugar de eliminar los archivos, puede moverlos a su destino previsto.

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

Usando FUSE

En lugar de depender de herramientas externas, puede (en la mayoría de los dispositivos) usar FUSE para manipular archivos usando comandos comunes del sistema de archivos.

Puede usar Fuse-zip para mirar dentro de un zip, extraerlo cp, enumerar su contenido find, etc.

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

AVFS crea una vista de toda la jerarquía de directorios donde todos los archivos tienen un directorio asociado (el mismo nombre con # al final) que parece contener el contenido del archivo.

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

Por fecha

Suponiendo que no haya habido ninguna otra actividad en la misma jerarquía que su extracción, puede ver los archivos extraídos por su ctime reciente . Si acaba de crear o mover el archivo zip, puede usarlo como punto de corte; de lo contrario, use ls -lctrpara determinar un tiempo de corte adecuado. Si desea asegurarse de no quitar las cremalleras, no hay razón para hacer ninguna aprobación manual: findes perfectamente capaz de excluirlas. Aquí hay ejemplos de comandos que usan zsh o find; tenga en cuenta que los primarios -cminy -cnewerno están en POSIX pero existen en Linux (y otros sistemas con GNU find), * BSD y 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

Con GNU find, FreeBSD y OSX, otra forma de especificar el tiempo de corte es crear un archivo y usarlo touchpara establecer su tiempo m al tiempo de corte.

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

En lugar de eliminar los archivos, puede moverlos a su destino previsto. Aquí hay una manera de encontrar GNU / * BSD / OSX, creando directorios en el destino según sea necesario.

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

Equivalente a Zsh (casi: este reproduce toda la jerarquía de directorios, no solo los directorios que contendrán archivos):

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

Advertencia, no he probado la mayoría de los comandos en esta respuesta. Siempre revise la lista de archivos antes de eliminar (ejecute echoprimero, luego rmsi está bien).

Gilles 'SO- deja de ser malvado'
fuente
Finalmente me encuentro con este problema hoy. Como root! Al final usé una combinación de "Por nombre" y "Por fecha"
phunehehe
1

Me siento estúpido, de todos modos me rasqué la cabeza para escribir este guión cuando tuve un problema similar. Solía cpiocon la -itbandera para obtener una lista de archivos; puede usar comandos equivalentes para otros archivadores. La parte difícil es que el archivo cpio es de un initrd y lo extraje /, por lo que muchas carpetas y archivos tienen el mismo nombre que en un sistema de trabajo. Afortunadamente, cpio no sobrescribió ninguno de mis archivos existentes. Utilizo una verificación de tiempo para asegurarme de no eliminar nada de lo que existía antes del comando incorrecto.

#! /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
phunehehe
fuente
0

¿Qué tal alimentar la lista de archivos en el archivo xargs rm?

Eso sería tar -tf tarbomb.tar | xargs rmo unzip --list zipbomb.zip | xargs rm.

alex
fuente
2
Los comandos dados no funcionarán en el caso general, y esto es peligroso ya que está eliminando archivos. xargsespera su entrada citada de una manera peculiar que findno produce. Use xargs -I rm {}para que xargs procese un artículo por línea en su lugar. Para el comando descomprimir, ¿qué implementación tienes? El mío (Debian / Ubuntu) no --listsolo tiene -l, y no solo imprime nombres de archivos, por lo que se necesita un procesamiento adicional.
Gilles 'SO- deja de ser malvado'
@Gilles: 1) sí, es peligroso, pero dado que presumiblemente hemos sobrescrito los archivos originales, ya se han ido. 2) no estaba hablando find. 3) estás en lo correcto unzip, no probé y parece que no hay opción para una lista sin decoración. No --listen mi Ubuntu también, simplemente no probé.
alex
Lo sentimos acerca de la respuesta almacenada, sustituir tar -ta find. Pero mis otros puntos se mantienen. Existe un riesgo real de que su comando tal como se borre elimine un archivo no relacionado.
Gilles 'SO- deja de ser malvado'
tar -tf tarbomb.tarimprimirá los nombres de archivo uno por línea, por lo que podría hacer tar -tf tarbomb.tar | while IFS=$'\n' read -r filename; do rm "$filename"; doneo similar.
Mikel
0

No es realmente lo que pediste, pero ¿qué tal si usas un script "descomprimir todo" en lugar de?

unzip *.zip

De esa manera, la salida de cada archivo va a su propio directorio.

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

Yo uso la siguiente función en zsh:

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

Es decir, la sustitución de comandos para eliminar todos los archivos en la salida limpia de unzip -l.

tar tvf podría usarse de manera similar.

Edd Steel
fuente