如何让 gzip 在所有深度上递归运行?

如何让 gzip 在所有深度上递归运行?

*.vtu我的意思是在 bash 中对给定目录下所有深度的所有文件进行 gzip 压缩。我在深度 1 和 2 下有这样的文件./。我设法这样做了

$ gzip -v $(find . -name "*.vtu")

我还可以使用find ... -exec,和其他组合(见下文)。
有没有办法仅使用 gzip 功能来实现这一点(-r这是我的候选人)?

我期望

$ gzip -r -v "*.vtu"

其中模式不会因外壳而扩展,而是会扩展gzip(并以某种方式产生我的预期结果!),可以解决这个问题,但我gzip: ...: No such file or directory尝试了所有组合都失败了。我发现以下情况:

  1. shopt -s globstar(来自这里),这个命令gzip -v **/*.vtu似乎完全符合我的要求。
  2. 如果shopt | grep globstar给出globstar off,则上述命令不起作用。在这种情况下,我可以使用gzip -v */*.vtu,但它仅适用于深度为 1 的文件。gzip -v */*/*.vtu深度为 2 的文件也同样如此。

无论如何,我没有发现 flag 的作用/用处是什么-r

有关的

  1. 使用 gzip 压缩所有具有特定扩展名的文件
  2. https://stackoverflow.com/questions/10363921/how-to-gzip-all-files-in-all-sub-directories-in-bash

答案1

不,gzip 无法做到这一点,-r它只是意味着“进入子目录”,但没有“进入子目录,然后查找与此 glob 匹配的文件”的选项。 glob 的扩展*.vtu发生在grep启动之前,并且由 shell 而不是处理grep,因此给出了一个特定的文件列表:当前目录中grep匹配的文件。*.vtu

所以是的,这globstar是你最好的选择。至于的用法-r,在中进行了解释man gzip

-r --recursive
       Travel the directory structure recursively.  If any of the file
       names  specified on the command line are directories, gzip will
       descend into the directory and compress all the files it  finds
       there (or decompress them in the case of gunzip ).

So 的意思是“如果是目录,则gzip -r foo进入该目录并对其中的文件进行 gzip 压缩”。如果同时匹配文件和目录,例如,如果您在运行的目录中同时拥有和,那么的内容也会被压缩。如果没有它,您将得到。foofoofoofile.vtumy.vtu/gzipmy.vtumy.vtu is a directory -- ignored

其他选项包括:

  • find . -name "*.vtu" -exec gzip {} +压缩所有匹配的文件。
  • gzip **/*.vtuglobstar设置。
  • find . -name "*.vtu" | xargs gzip(只要你的名字合理并且不包含换行符)
  • find . -name "*.vtu" -print0 | xargs -0 gzip(如果您的文件名可以包含换行符)

答案2

terdon 的回答,经过一番修改后,我得出结论,该-r工作方式如下:

  1. 如果匹配的是一个文件(仅在当前目录中)则执行gzip
  2. 如果匹配的是目录,则进入该目录,然后执行gzip -r *

对我来说,这非常奇怪(因此我从未想象过这是它的工作原理)。例如,如果./我有

foo
foo.vtk
test.vtk/
test.vtk/another.vtk/
test.vtk/another.vtk/cake.vtk
test.vtk/another.vtk/dow.txt
test.vtk/cake.vtk
test.vtk/dow.txt
test.vtk/this/
test.vtk/this/cake.vtk
test.vtk/this/dow.txt

命令gzip -r -v *.vtk将对除 之外的所有文件进行 gzip 压缩。所有子目录(depth=1) 和(depth>1)中的./foo所有文件(不仅仅是)都将被压缩。*.vtk*.vtk*gzip

答案3

这不是您问题的确切答案,但您可以使用xargs它,它允许您并行运行多个gzip进程,例如

find -name '*.vtk' -print0 | xargs -r0n1 -P$(nproc) gzip
  • 查找文件
    • 匹配*.vtk,引用,所以它不会被 shell 扩展
    • 打印由 NUL 字节分隔的文件名(以便具有明确的分隔符)
  • 将文件列表提供给xargs
    • 如果列表为空则不运行(-r),因为 gzip 会使用 stdin
    • 使用 NUL 作为分隔符 ( -0)
    • 每次调用使用一个文件名gzip( -n1)
    • 根据命令输出的 CPU-P数量,并行运行尽可能多的进程( )nproc
    • gzip对每个输入运行命令

相关内容