如何在命令行上压缩多个文件?


16

原谅这个最基本的问题,但是我在堆栈交换上找不到直接的答案或简单的例子。

假设我有一个文件文件夹,我想将其压缩为一个zip文件,可以与可怕的Windows朋友共享(否则,我只会使用tar并完成)。看起来像这样:

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

假设我已经zip安装了:

sudo apt-get install zip

从中man zip可以看出,它使我可以使用文件列表:

-@文件列表。如果文件列表指定为-@ [不在MacOS上],则zip从标准输入而不是从命令行获取输入文件的列表。例如,

          zip -@ foo

因此,我创建了zip.lst如下所示的内容:

cat zip.lst

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

现在我尝试了:

zip -@ zip.lst

但是除了在控制台上创建空白行外,它什么也没做。而且我可以继续推动Enter,并且只是在看似不执行命令的情况下仍使更多的空行成为可能。经过一番搜索,我意识到我需要通过按Ctrl+ 来终止输入D

但是现在我得到这个错误:

    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)

什么!?我的简单列表如何不是“有效的文件结构”?返回手册以获取更多信息,我将进一步研究:

如果文件列表指定为-@ ...

因此,我尝试不使用它-@,并且至少立即处理它而不必按Ctrl+,D但是我仍然遇到相同的错误

幸运的是,我找到对一个几乎不相关的问题的答案的评论,这使我意识到我需要显式命名该zip文件。发生此错误是因为默认情况下,它试图创建一个名为的zip文件zip.lst。但是,由于那是我列表的名称,因此可能会认为它只会覆盖它,但实际上,它是在尝试更新它。而且由于该列表显然不是zip文件,因此我们收到无效的文件结构错误,现在很清楚为什么它说“可能不是zip文件”。所以我尝试了:

zip files.zip zip.lst

adding: zip.lst (deflated 35%)

尤里卡!我可以看到该zip文件已创建,并且我的文件夹现在包含以下内容:

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

但是等我们庆祝之前,让我们先确认zip文件的内容:

unzip -l files.zip

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

没有!好吧,实际上这从标准用法上是有意义的,因为它只是压缩了我给它的一个列表文件。最后,我再次尝试,-@但得到了相同的结果。

我究竟做错了什么?

顺便说一句,我知道我可以使用GUI并用鼠标来完成此操作,但是我需要对此进行脚本编写,并且总的来说,当我知道自己在做什么时,使用CLI可以更快。

Answers:


23

使用文件<重定向

zip files.zip -@ < zip.lst

或者,您可以跳过列表,仅浏览

zip files.zip *.txt *.jpg

谢谢steeldriver

历史答案

我很高兴可以回答我自己的问题,因为我想记述我的动荡,希望通过搜索一些关键词可以避免别人在我的眼泪中掉队。

最终,我找到了正确的答案,但是答案却有

几点澄清:

  • 该手册不是像文件中那样引用文字列表,而是按字面意义在控制台上列出文件。
  • 可以理解有人可能会误以为是foo引用文件列表的原因,但这实际上是要表示输出zip文件的名称。
  • 在该示例中,文件列表被省略,因为它使用的是-@开关,这表明它“从标准输入而不是从命令行获取输入文件的列表”

了解了这一点,我们现在可以采用多种方法来实现目标。

首先使用我们创建的文件列表,我们可以使用读取列表cat并使用管道将输出重定向为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%)

看到adding: ...每个文件肯定是一个好兆头,但是我们之前抱有希望,所以让我们确认一下:

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

甜!但是谁又想创建一次性使用清单?这是解决这种特殊情况的可怕的绕行方式。最好从中获取列表ls并将其通过管道传输至zip:

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%)

极好!现在,让我们创建强大的过滤器,grep例如将jpg压缩起来:

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

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

或者只是以“ file”开头的文件

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%)

5
除了使用lsand grep和zip之外-@,您还可以使用shell glob在zip命令行上直接选择文件,例如zip files.zip file*zip images.zip *.jpg。另外,当使用文件中的文件名列表时,可以使用重定向而不是调用单独的cat进程,zip files.zip -@ < zip.lst
steeldriver

如何使嵌套目录与文件一起使用呢?
BallpointBen

我会使用@BallpointBen find代替ls
Jeff Puckett

6

最大压缩级别的最简单命令

zip -9 -r filename.zip /path/to/dir singlefile.jpg 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.