Bash string concatenation used to build parameter list

Given this piece of bash:

PARMS='-rvu'
PARMS+=" --delete --exclude='.git'"
echo $PARMS
rsync ${PARMS} . ${TARGET}

The echo shows the PARMS string as expected, no error is displayed, but rsync silently acts as if the options added by the += did not exist. However, this works as expected:

PARMS='-rvu'
rsync ${PARMS} --delete --exclude='.git' . ${TARGET}

I guess I screwed something up with bash quotes (always had problems with those), but not exactly sure what and why are the options ignored even though the string seems to have been built correctly.

Asked By: neuviemeporte

||

There is a difference between:

PARMS+="... --exclude='.git'"

and

... --exclude='.git'

In the first, the single quotes are inside quotes themselves, so they are literally present in the substituted text given to rsync as arguments. rsync gets an argument whose value is --exclude='.git'. In the second, the single quotes are interpreted by the shell at the time they’re written, because they aren’t inside quotes themselves, and rsync gets to see --exclude=.git.

In this case, you don’t need the single quotes at all — .git is a perfectly valid shell word on its own, with no special characters, so you can use it literally in the command.

Better for this kind of thing, though, is an array:

PARMS=(-rvu)
PARMS+=(--delete --exclude='.git')
rsync "${PARMS[@]}"

This builds up your command as separate words, with whatever quoting you want interpreted at the time you write the array line. "${PARMS[@]}" expands to each entry in the array as a separate argument, even if the argument itself has special characters or spaces in it, so rsync sees what you wrote as you meant it.

Answered By: Michael Homer

In addition to @Michael Homer’s answer, you can use bash eval function:

PARMS='-rvu'
PARMS+=" --delete --exclude='.git'"
echo "$PARMS"
eval "rsync ${PARMS} . "'"${TARGET}"'
Answered By: cuonglm
Categories: Answers Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.