I mean to gzip all files *.vtu
, at all depths below a given directory, in bash.
I have such files at depths 1 and 2 below ./
.
I managed to do so with
$ gzip -v $(find . -name "*.vtu")
I could also use find ... -exec
, and other combinations (see below).
Is there any way of doing it only with a capability of gzip (-r
was my candidate)?
I expected
$ gzip -r -v "*.vtu"
where the pattern would not be expanded by the shell but expanded by gzip
(and in a way to produce my intended result!), would work for this, but I get gzip: ...: No such file or directory
with all combinations I tried.
What I found is the following:
- With
shopt -s globstar
(from here), the commandgzip -v **/*.vtu
seems to do exactly what I want. - If
shopt | grep globstar
givesglobstar off
, the command above does not work. In this case, I can usegzip -v */*.vtu
, but it only works with files at depth=1. Likewise withgzip -v */*/*.vtu
at depth=2.
In any case, I didn't find what is the effect/usefulness of flag -r
.
Related:
No, gzip can't do this,
-r
just means "descend into subdirectories" but there is no option for "descend into subdirectories and then look for files matching this glob". The expansion of the*.vtu
glob happens beforegrep
is launched, and it is handled by the shell notgrep
, sogrep
is given a specific list of files: those files matching*.vtu
in the current directory.So yes,
globstar
is your best bet. As for the use of-r
, that is explained inman gzip
:So
gzip -r foo
means "descend intofoo
iffoo
is a directory and gzip any files in it". Iffoo
matches both files and directories, if for example you had bothfile.vtu
andmy.vtu/
in the directory you rangzip
in, then the contents ofmy.vtu
would also be compressed. Without it, you would getmy.vtu is a directory -- ignored
.Other options include:
find . -name "*.vtu" -exec gzip {} +
to compress all matching files.gzip **/*.vtu
withglobstar
set.find . -name "*.vtu" | xargs gzip
(as long as your names are sane and don't contain newlines)find . -name "*.vtu" -print0 | xargs -0 gzip
(if your file names can contain newlines)After the answer by terdon, and upon tinkering a bit, I came to the conclusion that the way
-r
works is the following:gzip
.gzip -r *
.For me, this is extremely weird (and therefore I would have never imagined this is how it works). For instance, if in
./
I havecommand
gzip -r -v *.vtk
would gzip all files except./foo
. All files (not only*.vtk
), in all subdirectories*.vtk
(with depth=1) and*
(with depth>1) would begzip
ped.Not an exact answer to your question, but you can use
xargs
for that, which allows you to run multiplegzip
processes in parallel, like*.vtk
, quoted so it is not expanded by the shellxargs
-r
) because gzip would then use stdin-0
)gzip
invocation (-n1
)-P
) as the output of thenproc
command says we have CPUsgzip
command for each input