如何在bash中压缩所有子目录中的所有文件

26

我想在当前位置的子目录中遍历并单独地对每个文件进行gzip压缩。对于一个目录中的文件进行压缩,我使用

for file in *; do gzip "$file"; done

但是这只能在当前目录中工作,而不能在当前目录的子目录中工作。我该如何重写上述语句,以便它也可以压缩所有子目录中的文件?

4个回答

63

我更喜欢使用gzip -r ./,它可以完成相同的工作,并且更加简洁。


4
难道不应该是最佳答案吗? - ghchoi
1
gzip -r -k -9 ./ - Rodrigo Soares
这确实是最优雅的答案。谢谢你。 - Abhimanyu Shekhawat
注意:-r选项并不总是可用的。在Ubuntu的gzip中是可用的,但是在BusyBox docker中(http://spblinux.de/2.0/doc/gzip.html)却不可用。 - undefined

59
不需要循环或者其他操作,只需使用findgzip即可:
find . -type f ! -name '*.gz' -exec gzip "{}" \;

这段代码会查找当前目录及其下层目录中所有以.gz扩展名结尾的非压缩普通文件,并对每个文件单独调用gzip命令进行压缩。


根据user unknown的评论进行编辑:

花括号({})将被替换为文件名,该文件名作为单个单词直接传递给-exec后面的命令,如下所示:

$ touch foo
$ touch "bar baz"
$ touch xyzzy
$ find . -exec echo {} \;

./foo
./bar baz
./xyzzy

2
你最后一句话是一个常见的错误信息。Find 知道文件名从哪里开始和结束。它本身没有任何与空格或换行符等有趣的事情相关的问题。因此,-exec gzip {} 调用 gzip 以单个文件名作为参数,由于没有调用中间 shell,也就不会将空格解释为分隔符,gzip 将接收整个文件名。find 的 manpage 中的提示似乎已经过时了,并且意味着:在将 {} 传递给 find 之前,您的 shell 可能会尝试解释它,但是多年来没有看到这样的 shell。参考链接 - user unknown
如何使用以下命令:“find . -type f -print0 | xargs -0r gzip”?实际上不需要排除.gz文件,因为gzip会保持它们不变:“gzip:foo.gz已经有.gz后缀--未更改” - FreeBird
find . -type f -print0 | xargs -0r gzip 也可以完美地工作,但它稍微不那么高效,因为它启动了一个新的 shell,处理了比必要更多的文件(即 .gz 文件),并生成了可以避免的输出。另一方面,如果你想看到 find 考虑的 所有 文件,这是一个很好的方法。像大多数任务一样,有很多方法可以完成这个任务,每种方法都有其优点和缺点。 - Adam Liss

6
find . -type f | while read file; do gzip "$file"; done

1
如果一个文件名包含空格或其他特殊字符,那么使用 for 循环就无法正常工作。 - c00kiemon5ter
1
@c00kiemon5ter 一个虽然不完整但是可行的答案是否应该被踩?根据SO的说法,“当你遇到极其草率、没有付出任何努力的帖子,或者明显而且可能危险地错误的回答时,请使用你的踩。” 这个答案没有上述情况。它可能不完整且有些草率,但并不是错误的。你应该让点赞过程发挥作用并留下评论。 - Tim Pote
我认为答案是错误的。Farshid从未指定文件不包含特殊字符,因此您的答案只回答了问题的一种特殊情况。最好使用 find .. | while read ..。纠正您的答案,我将成为第一个点赞的人。但请不要让我推广不正确(在我看来)的答案。 - c00kiemon5ter
因为你的答案更正确,但你不知道为什么把它删除了,所以我改变了我的答案成为你的那个。请注意,“不推广”并不一定意味着积极地踩。在看到你的评论后,我会修改我的答案或将其删除。 - Tim Pote

0

我还不能评论顶部帖子,但是我在"find"的man页面中看到-execDir比-exec更安全,因为命令是在找到匹配项的子目录中执行的,而不是在"find"运行的父目录中执行。

如果有人想使用正则表达式来定位子目录中特定文件并进行压缩,我建议使用

find ./ -type f -name 'addRegexHere' -execdir gzip -k "{}" \;

如果您不需要正则表达式,请使用上面(或下面,如果我有任何进展哈哈)的递归gzip调用。

源代码


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接