¿Cómo comprimo varios archivos en la línea de comandos?

16

Perdona esta pregunta más básica, pero no pude encontrar una respuesta directa o un ejemplo simple en el intercambio de pila.

Digamos que tengo una carpeta de archivos que me gustaría comprimir en un archivo zip que puedo compartir con mis terribles amigos de Windows (de lo contrario, simplemente lo usaría tary terminaría). Se parece a esto:

.
├── file1.txt
├── file2.txt
├── file3.txt
├── file.jpg
└── test.jpg

Suponiendo que haya zipinstalado:

sudo apt-get install zip

Veo man zipque me permite usar una lista de archivos:

- @ listas de archivos. Si una lista de archivos se especifica como - @ [No en MacOS], zip toma la lista de archivos de entrada desde la entrada estándar en lugar de desde la línea de comandos. Por ejemplo,

          zip -@ foo

Así que creé lo zip.lstque se ve así:

cat zip.lst

file1.txt
file2.txt
file3.txt
file.jpg
test.jpg

Y ahora lo intenté:

zip -@ zip.lst

Pero no hizo nada excepto crear una línea en blanco en la consola. Y puedo seguir presionando Entery simplemente sigue haciendo más líneas en blanco sin aparentemente ejecutar el comando. Después de algunas búsquedas, me di cuenta de que necesitaba terminar la entrada presionando Ctrl+D

Pero ahora me sale este error:

    zip warning: missing end signature--probably not a zip file (did you
    zip warning: remember to use binary mode when you transferred it?)
    zip warning: (if you are trying to read a damaged archive try -F)

zip error: Zip file structure invalid (zip.lst)

¿¡Qué!? ¿Cómo es que mi lista simple no es una "estructura de archivo válida"? Regreso al manual para más información, y miro más de cerca:

Si una lista de archivos se especifica como - @ ...

Así que lo intento sin -@, y eso al menos lo procesa de inmediato sin tener que presionar Ctrl+, Dpero me queda el mismo error .

Afortunadamente, encontré un comentario sobre una respuesta a una pregunta casi no relacionada que me llevó a darme cuenta de que necesitaba nombrar explícitamente el archivo zip. Este error se debió a que, de forma predeterminada, intentaba crear un archivo zip llamado zip.lst. Pero como ese es el nombre de mi lista, uno podría pensar que simplemente lo sobrescribiría, pero no, de hecho estaba tratando de actualizarlo. Y dado que la lista obviamente no es un archivo zip, obtenemos el error de estructura de archivo no válido, y ahora está claro por qué dice "probablemente no es un archivo zip". Entonces intenté:

zip files.zip zip.lst

adding: zip.lst (deflated 35%)

Eureka! Puedo ver que el archivo zip fue creado y mi carpeta ahora contiene esto:

.
├── file1.txt
├── file2.txt
├── file3.txt
├── file.jpg
├── files.zip
├── test.jpg
└── zip.lst

Pero espere antes de celebrar, confirmemos primero el contenido del archivo zip:

unzip -l files.zip

Archive:  files.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
       48  2016-05-24 15:30   zip.lst
---------                     -------
       48                     1 file

¡No! Bueno, en realidad eso tiene sentido por el uso estándar porque simplemente comprimió el único archivo de lista que le di. Finalmente intenté nuevamente con -@pero obtuve el mismo resultado.

¿Qué estoy haciendo mal?

Por cierto, sé que puedo usar la GUI y hacerlo con el mouse, pero necesito escribir esto, y en general soy más rápido en la CLI cuando sé lo que estoy haciendo.

Jeff Puckett
fuente

Respuestas:

23

Usar <redirección de archivos

zip files.zip -@ < zip.lst

O podrías saltarte la lista y solo pegar

zip files.zip *.txt *.jpg

gracias conductor de acero

Respuesta historica

Me alegra que esté bien responder a mi propia pregunta porque quería hacer una crónica de mi agitación con la esperanza de que otros que me siguieran en mi rastro de lágrimas pudieran evitar buscar algunas palabras clave.

Finalmente, descubrí la respuesta correcta , pero se publicó en la pregunta incorrecta .

Un par de puntos de claridad:

  • El manual no se refiere a una lista literal como en un archivo, sino literalmente a enumerar los archivos en la consola.
  • Es comprensible que alguien pueda ser engañado para pensar que se foorefiere a la lista de archivos, pero en realidad está destinado a representar el nombre del archivo zip de salida.
  • La lista de archivos se omite en el ejemplo porque está usando el -@interruptor, lo que demuestra que "toma la lista de archivos de entrada desde la entrada estándar en lugar de desde la línea de comandos "

Entendiendo esto, ahora estamos armados con una variedad de formas de lograr el objetivo.

En primer lugar, utilizando la lista de archivos que creamos, podemos leer la lista caty redirigir la salida con una tubería como entrada estándar a zip:

cat zip.lst | zip -@ files.zip

  adding: file1.txt (stored 0%)
  adding: file2.txt (stored 0%)
  adding: file3.txt (stored 0%)
  adding: file.jpg (stored 0%)
  adding: test.jpg (stored 0%)

Ver eso adding: ...para cada archivo es ciertamente una buena señal, pero hemos tenido esperanzas antes, así que confirmemos:

unzip -l files.zip

Archive:  files.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  2016-05-24 14:54   file1.txt
        0  2016-05-24 14:54   file2.txt
        0  2016-05-24 14:54   file3.txt
        0  2016-05-24 15:00   file.jpg
        0  2016-05-24 14:59   test.jpg
---------                     -------
        0                     5 files

¡DULCE! Pero, ¿quién quiere crear una lista de uso único de todos modos? Esa es una forma horrible de resolver este escenario en particular. Sería mejor obtener una lista lsy canalizar eso para comprimir:

ls | zip -@ files.zip

  adding: file1.txt (stored 0%)
  adding: file2.txt (stored 0%)
  adding: file3.txt (stored 0%)
  adding: file.jpg (stored 0%)
  adding: test.jpg (stored 0%)

¡Fabuloso! Ahora creemos filtros con el increíble poder de grepsimplemente comprimir los jpg, por ejemplo:

ls | grep .jpg | zip -@ images.zip

  adding: file.jpg (stored 0%)
  adding: test.jpg (stored 0%)

O simplemente archivos que comienzan con "archivo"

ls | grep file. | zip -@ files.zip

  adding: file1.txt (stored 0%)
  adding: file2.txt (stored 0%)
  adding: file3.txt (stored 0%)
  adding: file.jpg (stored 0%)
Jeff Puckett
fuente
55
En lugar de usar lsy grepy zip -@, puede usar globos de shell para seleccionar archivos directamente en la línea de comando zip, por ejemplo, zip files.zip file*o zip images.zip *.jpg. Además, cuando use una lista de nombres de archivo de un archivo, puede usar la redirección en lugar de invocar un proceso cat separado,zip files.zip -@ < zip.lst
steeldriver
¿Cómo puede hacer que esto funcione con directorios anidados junto con archivos?
BallpointBen
@BallpointBen que usaría en findlugar dels
Jeff Puckett
6

El comando más simple con un nivel de compresión máximo

zip -9 -r filename.zip /path/to/dir singlefile.jpg 
Ansyori
fuente