0
RSYNC="rsync -avzhe 'ssh -i /path/to/deploy_keys/id_rsa' --delete "

# Files
$RSYNC deploy@ip:/var/www/path1 /var/www/path1
$RSYNC deploy@ip:/var/www/path2 /var/www/path2

I'd like to introduce this RSYNC Variable to be more compact, but it throws an error:

Unexpected remote arg: deploy@ip:/var/www/path1

If i use only rsync inside the doublequotes, it works fine. For the sake of readability, i'd keep them separate command invocations.

Aron Novak
  • 314
  • 1
  • 14

3 Answers3

4

I agree that eval is dangerous. In addition to the array approach @Eugeniu Rosca suggested, you could also use a shell function:

my_rsync() {
    rsync -avzhe 'ssh -i /path/to/deploy_keys/id_rsa' --delete "$@"
}

my_rsync deploy@ip:/var/www/path1 /var/www/path1
my_rsync deploy@ip:/var/www/path2 /var/www/path2

BTW, you should read BashFAQ #50: I'm trying to put a command in a variable, but the complex cases always fail!.

Gordon Davisson
  • 118,432
  • 16
  • 123
  • 151
2

If you want to store the command string into a variable and evaluate it later, you can use eval or an alternative safer technique:

#!/bin/bash

# Store the command into an array
RSYNC=(rsync -avzhe 'ssh -i /path/to/deploy_keys/id_rsa' --delete)
# Run the command
"${RSYNC[@]}" deploy@ip:/var/www/path1 /var/www/path1

Why eval should be avoided

Community
  • 1
  • 1
Eugeniu Rosca
  • 5,177
  • 16
  • 45
1

After you assign a string to a variable and then submit it to shell again it is tokenized differently. Consider the following script

VAR="/bin/ls 'Test1 Test2'"
$VAR

It will throw two errors:

/bin/ls: cannot access 'Test1
/bin/ls: cannot access Test2'

You guessed it right, the apostrophes are no longer affecting tokenization. Instead they are treated as normal characters when the commandline arguments are fed to /bin/ls

While eval is rightly considered evil, it is by far the easiest way to get a script running. It stitches all the arguments into one line and applies the tokenizing procedure again.

RSYNC="rsync -avzhe 'ssh -i /path/to/deploy_keys/id_rsa' --delete "

# Files
eval $RSYNC deploy@ip:/var/www/path1 /var/www/path1
eval $RSYNC deploy@ip:/var/www/path2 /var/www/path2
Dima Chubarov
  • 16,199
  • 6
  • 40
  • 76