Your issue has to do with the way you use your string $OPTSTR
. This is a string of multiple space-separated words, and since you use it unquoted, you make the shell split it into a list of separate words. However, the shell will not perform an extra quote removal step, so the single quotes in the string will be literal. You command therefore excludes files and directories named '.cache'
, not .cache
. You would also have issue had you needed to use strings with spaces in them, or globbing patterns.
In short: Do not put separate things, that needs to be kept separate, in a single string.
Instead, use a list:
#!/bin/sh
src_dir=/home
dest_dir=/backup/test
set -- -v -a -x -HAX --delete --exclude='.cache/'
rsync "$@" "$src_dir/" "$dest_dir"
This sets the list of positional parameters to the options that you later want to use with rsync
. Each parameter will be correctly handled, even if it contains quoted string with embedded spaces and globbing characters, as long as the expansion of $@
is double quoted.
Or, if you use bash
, you may use a named array,
#!/bin/bash
src_dir=/home
dest_dir=/backup/test
opts=( -v -a -x -HAX --delete --exclude='.cache/' )
rsync "${opts[@]}" "$src_dir/" "$dest_dir"
Also related: