doing own custom parameters

I have an rsync command that I want to create a variable where user can change to customize the parameters.

complete rsync command to run:

$RSYNC -e 'ssh -ax -o ClearAllForwardings=yes' --log-file=$LOG_FILE --delete -avzcr -u  --update $SRC_DIR $USER@$TRG_SRV:$TRG_DIR >> $LOG_FILE

What I want to do is separate our the parameters into a variable:

rsync_param="-e 'ssh -ax -o ClearAllForwardings=yes' --log-file=$LOG_FILE --delete -avzcr -u  --update"

Then I modify the rsync to run as below:

$RSYNC $rsync_param $SRC_DIR $USER@$TRG_SRV:$TRG_DIR >> $LOG_FILE

But it doesn't work. I get syntax error. But when I echo out the command, it is same as the original command.

Any idea how to solve this?

When you assign the string to the variable $rsync_param it will take the [bold]current[/bold] value of the variable $LOG_FILE, which may or may not be set (you haven't shown any context) so that when rsync comes to run it sees --log-file=
which would be a syntax error.

I've run into this issue when I wrote an man rsync (linux) script, in which I had to man eval (linux) the command to get things to work properly, as in:

eval $RSYNC $rsync_param $SRC_DIR $USER@$TRG_SRV:$TRG_DIR >> $LOG_FILE

To demonstrate what is happening, I created a quick script to display the number of parameters, and the parameters themselves:

#! /bin/sh

echo '#:' ${#}
while [[ 0 -lt ${#} ]]; do echo "${1}"; shift; done | cat -n

And here are the results:

trogdor $ ./countem a b c d
#: 4
     1    a
     2    b
     3    c
     4    d

trogdor $ ./countem a 'b c' d
#: 3
     1    a
     2    b c
     3    d

Which is as expected. But if we:

trogdor $ ARGS="a 'b c' d"

trogdor $ ./countem ${ARGS}
#: 4
     1    a
     2    'b
     3    c'
     4    d

${ARGS} is expanded into four tokens. Double-quoting doesn't help either:

trogdor $ ./countem "${ARGS}"
 #: 1
     1    a 'b c' d

What you need to do is have the shell re-parse your command line, so that it is recognizes the quoting within your variables:

trogdor $ eval ./countem "${ARGS}"
  #: 3
     1    a
     2    b c
     3    d

Or without the quotes:

trogdor $ eval ./countem ${ARGS}
#: 3
     1    a
     2    b c
     3    d

Be warned, the script will evaluate the command line twice. Be careful with characters that will cause command line expansion.

1 Like

thanks for the explanation. Now I understand what's the problem and usage of "eval".

I manage to solve the problem by dumping the whole command into another variable and then use eval on that variable.

run_rsync="$RSYNC $rsync_param $SRC_DIR $USER@$TRG_SRV:$TRG_DIR >> $LOG_FILE"
eval $run_rsync

Tested and it seems to be running.

Thanks again for the great help. :b:

Most awsome post mr ludwig. I have been having trouble with understanding what exactly eval was good for. Now I know too.

I would be interested in an example of a situation where this doesn't work as you were warning about.