¿Cómo puedo forzar descomprimir / zip para no crear un subdirectorio cuando lo extraigo?

19

Dependiendo de cómo se cree un archivo zip, a veces extraerá todos los archivos directamente, y a veces los extraerá en un subdirectorio.

Si esto último es cierto, ¿cómo puedo obligar al unzipcomando a "ignorar" ese directorio de primer nivel?

Ejemplo:

cd /tmp
wget http://omeka.org/files/omeka-1.5.1.zip
mkdir omeka
unzip omeka-1.5.1.zip -d omeka/
cd omeka/
ll

Lo que estoy obteniendo es /tmp/omeka/omeka-1.5.1/:

total 12
drwxr-xr-x 3 root root 4096 2012-05-08 18:44 ./
drwxrwxrwt 6 root root 4096 2012-05-08 18:44 ../
drwxr-xr-x 5 root root 4096 2012-04-20 14:54 omeka-1.5.1/

Lo que quiero es de los archivos extraídos /tmp/omeka/(un nivel superior y ningún número de versión incluido en la estructura del directorio)

/tmp/omeka/(files)

Sé que puedo usar la -jopción de "rutas basura", pero quiero mantener la estructura del subdirectorio, pero no la estructura del directorio de nivel superior. ¿Cómo puedo hacer esto?

cwd
fuente
PD: Soy consciente de que puedo extraer y luego mvlos archivos, pero quería ver si había una manera de hacerlo directamente desde el comando descomprimir
cwd
No estoy al tanto de uno. Pero si el nombre del archivo siempre coincide (aparte de la extensión) con el nombre del directorio, es bastante sencillo escribir el nombre del directorio extraído.
Mat
3
Veo lo que intentas hacer, pero no lo recomendaría. Eliminar el número de versión de las fuentes de su proyecto es una mala idea; simplemente debe extraer normalmente y usar un ln -s si desea un nombre más corto sin información de versión. De esa manera, siempre sabrá qué versión está ejecutando y puede actualizar fácilmente a una nueva versión cambiando el enlace.
Burton Samograd
@BurtonSamograd: eso sería ideal, pero todavía tengo curiosidad por saber si hay una manera efectiva de hacerlo porque algún software, tome Wordpress como ejemplo, coloca cada versión dentro de un /wordpress/directorio (sin número de versión) dentro del archivo zip. De hecho, está bien unzip, mvpero no tener control de esto y tener que hacerlo en dos pasos siempre me ha puesto un poco nervioso. Afortunadamente, Wordpress también tiene un .tar.gzsabor :)
cwd
Pruebacd /tmp/omeka && ln -s -T . omeka-1.5.1
James Youngman

Respuestas:

4

Utilice un sistema de archivos FUSE que le permita explorar archivos como directorios, como AVFS . Use cppara extraer los archivos al directorio de su elección.

mountavfs
cp -Rp ~/.avfs/tmp/omeka-1.5.1.zip\#/omeka-1.5.1 omeka

Como suponemos que hay un único directorio de nivel superior en el archivo, puede acortar esto a

cp -Rp ~/.avfs/tmp/omeka-1.5.1.zip\#/* omeka
Gilles 'SO- deja de ser malvado'
fuente
@Giles, usted es el experto que viene y responde todas las preguntas que nadie más puede responder, así que supongo que esta es realmente la única forma de hacerlo. Esperaba unziptener algo de magia para hacer esto, como especificar los archivos a extraer */*, que podría usar sin instalar otra utilidad, pero supongo que no. Gracias. +1
cwd
6

Si su archivo zip no contiene estructura de directorio o no necesita preservarlo, puede usar esto:

cd /tmp
wget http://omeka.org/files/omeka-1.5.1.zip
unzip -j omeka-1.5.1.zip -d omeka
cd omeka
ll
Eneko Alonso
fuente
3

Este script no es robusto, pero funciona en casos simples:

...
dest=omeka
unzip omeka-1.5.1.zip -d $dest/

if [ `ls $dest | wc -l` == 1 ]; then
  subdir=`ls $dest`
  mv $dest/$subdir/* $dest/
  rmdir $dest/$subdir
fi

Simplemente verifica si hay exactamente un subdirectorio, y si es así, mueve todo hacia arriba y luego lo elimina.

Steve Bennett
fuente
2

Me acabo de registrar hoy, así que no puedo votar a favor de la respuesta de @SteveBennet y no puedo agregar un comentario allí.

Basado en su respuesta, creé una función recursiva como esta:

...

shopt -s dotglob # To include hidden files in the move command

function moveSub {
  local dest=$1
  if [ `ls $dest | wc -l` == 1 ]; then
    local subdir=`ls $dest`
    moveSub "$dest/$subdir"
    mv $dest/$subdir/* $dest/
    rmdir $dest/$subdir
  fi
}

moveSub "$dest"

Justo como dijo @SteveBennet: este script no es robusto, pero funciona en casos simples.

Espero que sea útil.

elysch
fuente
1

Necesidad parece patch --strip=nopción

Sería deseable tener una opción como patch --strip=number(o -pnumber) que corte los numbercomponentes de la ruta al principio (ref. Comparación y combinación de archivos: parchear directorios ).

Otra solución, aplicabilidad

De lo contrario, hay otra solución, algo hack pero funciona. En mi caso, quería sobrescribir un directorio lleno de archivos existentes con el contenido de un zip, sin extraer primero el zip completo.

Cuando esta solución funcione y la solución de @ Gilles esté disponible, esta última también funcionará. Sin embargo, esta solución no requiere la disponibilidad de un sistema de archivos FUSE.

Cómo hacerlo

Suponiendo que conoce el directorio adicional, en su caso omeka-1.5.1, puede hacer esto:

mkdir omeka
ln -s . omeka/omeka-1.5.1 # create a symlink that redirects output
unzip omeka-1.5.1.zip -d omeka/
rm omeka/omeka-1.5.1 # remote symlink

unzipintentará descomprimir a lo omeka-1.5.1que en realidad es un enlace simbólico para contener el directorio. Como resultado, los archivos aterrizarán omekadirectamente.

Posibles variantes

Puede imaginar variantes para redirigir una o más partes de una jerarquía dependiente.

ln -s ../myfoo omeka/omeka-1.5.1/foo
ln -s ../../mybarxyzzy omeka/omeka-1.5.1/subdir/bar

Conclusión

Esta solución es algo específica, pero tiene sus casos de uso y simplemente la usé.

Stéphane Gourichon
fuente
¡Gran solución si conoces el camino!
grepsedawk
La ruta se puede explorar enumerando primero el contenido zip, por ejemplo, con unzip -l. Esto incluso podría automatizarse utilizando un script que descubra parte de la ruta que es común.
Stéphane Gourichon
Oh, totalmente, es mucho más fácil si conoces el camino. Jugué con descomprimir -l por un tiempo, pero fue un poco más grep / sed / awk de lo que pretendía, así que me retiré.
grepsedawk
zipinfo -1Puede ser un buen comienzo. ¿Cuál es su caso de uso?
Stéphane Gourichon
github.com/grepsedawk/wow-config/blob/… en este caso, conozco el directorio :)
grepsedawk
1

Lo más probable es que quieras correr unzipcon la -jopción, como en:

unzip -j files.zip -d ./output/

Pero puede que te sorprenda su comportamiento:

-j caminos basura. La estructura del directorio del archivo no se recrea; Todos los archivos se depositan en el directorio de extracción (por defecto, el actual).

Si extrae files.zipen el directorio de salida ./outputy obtiene esto como resultado:

./output/files/subfolder1/f1
./output/files/subfolder1/f2

entonces la -jopción le dará esto (todas las rutas rayadas):

./output/f1
./output/f2
Vincenzo Pii
fuente