I've been reading about quotes in bash here and everywhere else, but i got no help solving this problem.
The thing is, I have a little script for doing backups in a loop.
If I don't use eval
then I have problems with $OPTIONS
variable in rsync
.
But if I do use eval
then the problem goes to the variable $CURRENT_DIR
...
rsync returns the following message: 'Unexpected local arg: /path/with'
I've tried every way of quoting the variable $CURRENT_DIR
CURRENT_DIR="/path/with spaces/backup"
DIR="dir_by_project"
f=":/home/project_in_server"
OPTIONS="-avr --exclude 'public_html/cms/cache/**' --exclude 'public_html/cms/components/libraries/cmslib/cache/**' --delete"
eval rsync --delete-excluded -i $OPTIONS [email protected]$f $CURRENT_DIR/xxx/$DIR/files
Is there any way that i can use the variable $CURRENT_DIR
without problems caused by spaces?
There are many shell constructs that end up being evaled, expanded, etc. and focussing only on eval is bad as it creates a false sense of security. It's important to understand the risk of working with any untrusted data and how it could be exploited.
$_ (dollar underscore) is another special bash parameter and used to reference the absolute file name of the shell or bash script which is being executed as specified in the argument list. This bash parameter is also used to hold the name of mail file while checking emails.
eval [arg ...] The args are read and concatenated together into a single command. This command is then read and executed by the shell, and its exit status is returned as the value of eval. If there are no args, or only null arguments, eval returns 0.
eval rsync --delete-excluded -i $OPTIONS [email protected]$f "\"$CURRENT_DIR/xxx/$DIR/files\""
command "some thing"
executes command with one argument some thing
. The quotes are parsed by the shell and arguments are setup as an array when executing the command. The command will see an argument as some thing without the quotes.
The eval command treats its arguments more or less as if they were typed into the shell. So, if you eval command "some thing"
, bash executes eval
with two arguments: command
and some thing
(again the quotes are eaten while bash sets up the array of arguments). So, eval then acts as if you typed command some thing
in the shell, which is not what you want.
What I did was simply to escape the quotes, so that bash passes literally "some thing" including the quotes to eval. eval then acts as if you typed command "some thing"
.
The outer quotes in my command is not strictly required, they're just habit. You could just as well use:
eval rsync --delete-excluded -i $OPTIONS [email protected]$f \"$CURRENT_DIR/xxx/$DIR/files\"
Using eval is dangerous, and should be avoided whenever possible. In this case, the primary problem is that you're trying to define OPTIONS as containing multiple words, and bash variables don't handle this very well. There is a solution: put OPTIONS in an array, instead of a simple variable (and use double-quotes around all variable references, to keep spaces from getting treated as word separators).
CURRENT_DIR="/path/with spaces/backup"
DIR="dir_by_project"
f=":/home/project_in_server"
OPTIONS=(-avr --exclude 'public_html/cms/cache/**' --exclude 'public_html/cms/components/libraries/cmslib/cache/**' --delete)
rsync --delete-excluded -i "${OPTIONS[@]}" "[email protected]$f" "$CURRENT_DIR/xxx/$DIR/files"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With