Reputation: 22356
Problem: Calling rsync
from a Zsh-script, I want to tell rsync to exclude files having one of a certain set of extensions. The way I'm doing this now is:
rsync -r --exclude '*.bak' --exclude '*.save' --exclude '*.backup' --exclude '*.old' ... from_directory/* to_directory
This is tedious to write and the command line get pretty lengthy. I tried as alternative
# THIS DOES NOT WORK:
rsync -r --exclude '*.bak' --exclude '*.{save,backup,old,...}' from_directory/* to_directory
but this doesn't work - rsync
doesn't handle the short cut using curly braces (which is not really surprising, because even on shell level, this is not part of the file globbing, but occurs in an earlier stage of the interpretation of the command line).
I also considered writing all the pattern to be excluded into a file and use --exclude-list
instead of --exclude
. This would work, but I don't like this solution, because I wanted my script to be self-contained, i.e. the file pattern are visible inside the script, not in a separate file.
Of course there is always the solution to create a temporary file, containing the extensions, using a HERE document:
cat <<<LIST >excluded.txt
*.bak
*.save
... etc
LIST
rsync -r --exclude-list excluded.txt ....
rm excluded.txt
but I wonder whether there is a more elegant solution, either by some clever use of rsync options, or by some Zsh feature which makes the handling the temporary file easier.
Upvotes: 2
Views: 1043
Reputation: 18429
The alternative you tried does not work because brace expansion (foo{a,b,c}bar
→ fooabar foobbar foocbar
) is not done for quoted braces.
Try the following instead.
rsync -r --exclude='*'.{bak,save,backup,old} from_directory/* to_directory
The trick is to quote only *
and use the fact that the values for the --exclude
option can also be separated with an =
instead of a space. That way zsh
recognizes it as one word and
--exclude='*'.{bak,save,backup,old}
will be expanded to
--exclude='*'.bak --exclude='*'.save --exclude='*'.backup --exclude='*'.old
Upvotes: 3