压缩目录中的所有文件?


482

是否可以使用zip命令将所有文件压缩到给定目录中?我听说过使用*.*,但是我也希望它也可用于无扩展名的文件。


2
您是否尝试过从所需目录向上导航并执行操作zip myarch.zip mydir/*
Joseph R.

13
或更好zip -r myarch.zip mydir/*
Adam

25
或更好zip -r myarch.zip mydir
ctrl-alt-delor

*.*表示任何带点的文件。在cp / m和dos中,所有文件都有一个点,这使您键入它(不能这样做*)。因此人们开始将*.*所有文件视为。最终,Microsoft添加了长文件名,该文件名可以包含零个或多个点。要查找Windows上带有点的文件,必须键入*.*.*
ctrl-alt-delor

Answers:


704

你可以用*; 不需要*.*。文件扩展名在Unix上并不特殊。*匹配零个或多个字符,包括一个点。因此它与匹配foo.png,因为它是零个或多个字符(准确地说是七个)。

请注意,*默认情况下不匹配以点开头的文件(都不匹配*.*)。这通常是您想要的。如果不是,则使用bash(如果shopt -s dotglob可以)(但仍会排除...)。其他Shell包含点文件的方式有所不同(或根本没有)。

另外,zip还有一个-r(递归)选项可以一次完成整个目录树(而不必担心dotfile问题):

zip -r myfiles.zip mydir

文件所在mydir的目录在哪里。请注意,生成的zip将包含目录结构以及文件。正如peterph在他的评论中指出的那样,这通常被视为一件好事:提取zip文件将把所有提取的文件整齐地存储在一个子目录中。

您也可以使用-j/ --junk-paths选项告诉zip不要存储路径。

zip命令附带了文档,告诉您所有(许多)选项的信息。输入man zip以查看该文档。这不是zip独有的。您可以通过这种方式获取大多数命令的文档。


9
您可能想补充一点,将归档文件中的所有内容都包含在顶层目录中是一种好习惯,这样一来,提取时就不会污染当前目录。
彼得2012年

@peterph完成了。恐怕这在zip文件中比在tarfile中要少一些惯例。
derobert

不幸的是。可能是由于Windows继承了Windows的传统,而Windows则继承了使用源代码的传统。
彼得2012年

2
请记住,*shell globbing不包含点文件(即以开头的文件名.)。这是按名称压缩整个目录的另一个优点。
mrb

但是使用-r包括目录本身,这破坏了我的工作。*不会包含...吗?
tkbx

11

就我而言,我想将每个文件压缩到自己的存档中,所以我做了以下操作(在中zsh):

$ for file in *; do zip ${file%.*}.zip $file; done

1
这里没有mkv?同样,这里没有什么特别zsh特定的。您将要正确地引用任何包含文件名的变量,因此zip "${file%.*}.zip" "$file"在两个变量周围都用双引号引起来。
人间

1
@tripleee首先,感谢您指出我对的错误引用mkv。其次,zsh与中不同,在中不需要引号bash。这就是为什么我指定这是的命令的原因zsh
Radon Rosborough

用“&”代替最后一个分号可能会大大加快速度(如果目录中的文件数量合理...)。否则find . -type f -maxdepth 1 -print0|xargs -r0 -n1 -P64 -I{} bash -c 'f="{}"; zip "${f%.*}.zip" "$f"'-P根据您的CPU线程进行调整...)(许多GNU依赖项...)
Gert van den Berg,

5

另一种方法是使用find和xargs :(这可能在zip中包含一个“。”目录,但它仍应正确提取。在我的测试中,zip在压缩前将点剥离了) find . -type f -exec zip zipfile.zip {} +

(如果您的的版本不支持exec 的结尾+\;则可以将其替换为。不过,它会更慢...)find+

默认情况下,这将包括所有子目录。在GNU上找到-maxdepth可以防止这种情况的发生。


(与使用的解决方案不同*,它将包含点文件,并且如果目录中的文件太多也不会掉落)
Gert van den Berg,

1

另一个(慢速)方法可以做到这一点(一次将一个文件添加到zip):

for f in * .[^.]*; do
    [ -r "$f" ] || continue # Skip directories or non-existant files (Probably ".[^.]*" if directory has no dotfiles). Using -e will allow directories to be used as well
    zip zipfile.zip "$f" # If directories are included, you probably want to add -r
done

这具有dotfile问题*(已添加解决方法),并且将为每个文件启动zip一次,并将其添加到存档中。在中bash,它将处理大量文件。

它会比大多数其他方法慢,但相对简单。


1
我会说这比接受的答案要简单,但速度较慢,这提示了一个问题:“为什么有人会这样做?”。如果您可以回答该问题,我建议您将上下文放在您的回答中,否则我认为这对于已经有好的回答的旧问题是一个不好的回答。
Centimane

@Centimane:我注意到了局限性。我觉得这具有教育意义。(如果不跳过目录,则非常简单)。如果您想要使用(标准)外部工具更快的答案,我的其他答案将对此进行介绍。(删除了dotfiles处理(这会影响正确性,而不会在问题中提及它们的缺失),我觉得这很优雅):for f in *; do zip zip.zip "$f"; done
Gert van den Berg

1
请注意,可接受的答案不使用外部命令,并且会更快。在什么情况下此答案有用?
Centimane

@Centimane使用tar时,文件数量超过bash可以作为参数传递的数量。(find + xargs更好,因为循环更容易...)。这是对这个问题的(唯一)答案。当然,这不是最佳答案。(如果某人的情况略有不同,则非最佳答案对于类似问题仍然有用,例如,希望tar文件中包含任何目录)
Gert van den Berg,
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.