I am running a rsync script and I want to exclude certain folders. I know with rsync you have to create a .txt file and add all the excludes in there but I am wondering is it possible to just have a global string in the script that includes all the excludes I want and then just added that global into the rsync command?

Global String Example

ROOT_EXCLUDE="--exclude=/dev --exclude=/proc --exclude=/sys --exclude=/temp --exclude=/run --exlucde=/mnt --exlcude=/media

Rsync Command

rsync -au --exclude 'ROOT_EXCLUDE' /Users/Me/Home /Users/me/Backup
  • 2
    Try just $ROOT_EXCLUDE instead --exclude 'ROOT_EXCLUDE'
    – Costas
    Apr 7 '15 at 11:31
  • You are also missing the ending " for the ROOT_EXCLUDE
    – GMaster
    Apr 7 '15 at 11:55
  • @Costas that didnt work, I just stuck to the normal way with a .txt file
    – patrick
    Apr 7 '15 at 11:55
  • @GMaster that was just an error in copying the code over
    – patrick
    Apr 7 '15 at 11:56
  • Try: export ROOT_EXCLUDE="--exclude=/dev --exclude=/proc --exclude=/sys --exclude=/temp --exclude=/run --exlucde=/mnt --exlcude=/media" And then: rsync -au $ROOT_EXCLUDE /Users/Me/Home /Users/me/Backup
    – GMaster
    Apr 7 '15 at 11:57

If the elements of your exclude list don't contain any whitespace or any wildcards, you can define a ROOT_EXCLUDE variable and use it unquoted. Unquoted variable expansions split the value of the variable at each whitespace sequence¹; then each element is expanded as a wildcard pattern if it contains any wildcard.

ROOT_EXCLUDE="--exclude=/dev --exclude=/proc --exclude=/sys --exclude=/temp --exclude=/run --exclude=/mnt --exclude=/media"
rsync -au $ROOT_EXCLUDE /Users/Me/Home /Users/me/Backup

If you want to use wildcards in the exclusion list, that will work in standard shells provided that you have no file whose name matches the pattern. That's a slippery assumption for words like --exclude=*.bak and often not the case if you write --exclude *.bak. To avoid this pitfall, you can turn off wildcard expansion.

ROOT_EXCLUDE="--exclude=/dev --exclude=*.bak"
set -f
rsync -au $ROOT_EXCLUDE /Users/Me/Home /Users/me/Backup
set +f

In shells that support arrays (ksh, bash, zsh, but not plain sh), you can put the list of arguments in an array. This is the recommended method to stuff a list of arguments into a variable.

ROOT_EXCLUDE=('--exclude=/dev' '--exclude=*.bak')
rsync -au "${ROOT_EXCLUDE[@]}" /Users/Me/Home /Users/me/Backup

Plain sh (any Bourne/POSIX shell, e.g. sh or dash) has a single unnamed array (the positional parameters $1, $2, …) which you can set with set -- …. If you need to temporarily change the positional parameters, make the temporary change in a function: each function call has its own set of positional parameters.

set -- '--exclude=/dev' '--exclude=*.bak'
rsync -au "$@" /Users/Me/Home /Users/me/Backup

Rather than spell out a list of directories to exclude, you should pass the -x option, to skip mount points. This will take care of /proc, /sys, etc. You will then however need to explicitly include all sources if you want to back up files across multiple partitions. If you're backing up home directories, there probably aren't in-memory filesystems to skip anyway, but there might be network filesystems or other FUSE filesystems.

rsync -ax /Users/Me/Home /Users/me/Backup

¹ More generally, based on the value of IFS.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.