user1934428
user1934428

Reputation: 22356

Excluding files with a certain set of extensions to be copied by rsync

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

Answers (1)

Adaephon
Adaephon

Reputation: 18429

The alternative you tried does not work because brace expansion (foo{a,b,c}barfooabar 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

Related Questions