bash expansion

I'm writing a script to do a bunch of rsync'ing.  I noticed there's a difference between:

rsync -avuzb --exclude '*.pdf' src dst

and

X="--exclude '*.pdf'"
rsync -avuzb $X src dst

For some reason, the second example doesn't work even though it should be identical to the first.

So the get some insight, I turn on the special -x debug mode at a Bash prompt:

$ set -x

$ X="--exclude '*.pdf'"
+ X='--exclude '\''*.pdf'\'''


$ echo $X
+ echo --exclude ''\''*.pdf'\'''
--exclude '*.pdf'

So it appears that Bash is escaping the single-quotes in the double-quoted string.  Echo seems capable of stripping this out, but rsync doesn't seem to, and gets tripped up.

I realize there are workarounds, eg:

X="--exclude \*.pdf"

But I'm wondering why the more readable example above doesn't work?  What's so weird about single quotes within double quotes.

Thanks,
LVL 19
Kim RyanIT ConsultantAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

ozoCommented:
what do you get from
perl -e 'print map"{$_}",@ARGV' -- -avuzb $X src dst
and
perl -e 'print map"{$_}",@ARGV' -- -avuzb --exclude '*.pdf' src dst
rsync should see the same thing
0
Kim RyanIT ConsultantAuthor Commented:
I need to run this as a bash shell script, not Perl.
0
ozoCommented:
I know, I just wanted to use perl to verify what the bash script was actually passing to rsync
0
Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

NopiusCommented:
rsync -avuzb --exclude '*.pdf' src dst
and
X="--exclude '*.pdf'"
rsync -avuzb $X src dst

These lines are not the same because  "--exclude '*.pdf'" becomes single non-splittable string and it is passed as 1 parameter to rsync
Using this syntax should avoid such behaveour:
X='*.pdf'
rsync -avuzb --exclude $X src dst



0
NopiusCommented:
Sorry, my suggestion where incorrect, I've straced this command and and rsync receives argc=6.
So the problem is in escaping.
0
Kim RyanIT ConsultantAuthor Commented:
$ X="--exclude '*.pdf'"
$  perl -e 'print map"{$_}",@ARGV' -- -avuzb $X src dst
{-avuzb}{--exclude}{'*.pdf'}{src}{dst}
$ perl -e 'print map"{$_}",@ARGV' -- -avuzb --exclude '*.pdf' src dst
{-avuzb}{--exclude}{*.pdf}{src}{dst}

Hmmm... so when '*.pdf' is part of a double-quoted string, the single quotes remain intact as they get passed in as $X, whereas they get stripped out by the shell in the second example.

>Using this syntax should avoid such behaveour:
>X='*.pdf'
>rsync -avuzb --exclude $X src dst

This won't work (I tried) because the second line gets expanded out to:

rsync -avuzb --exclude *.pdf src dst

And the shell expands *.pdf into individual files...
0
NopiusCommented:
You don't need extra double quotes for X:

X='--exclude *.pdf'
rsync -avuzb --exclude $X src dst

this works fine.
0
ahoffmannCommented:
> rsync -avuzb --exclude '*.pdf' src dst
passes the literal string *.pdf to rsync

> $ X="--exclude '*.pdf'"
here the shell (bash) evaluates *.pdf and globs the matching files
also keep in mind that $X then is one string which contains spaces, probably something rsync does not understand.

> X="--exclude \*.pdf"
escapes the * from the shell, no file globing done when setting X
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Linux OS Dev

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.