I have a call

./run.sh name --vars="service_name='someothername'"

and I'm trying to call another program with exactly same --vars="service_name='someothername'" argument from run.sh, however when ever I do, Bash puts single quotes around the $2 variable when I try to do

cmd=$(runother $2 | process output)

I get one of

  • runother '"--vars=service_name='\''someother..
  • runother '--vars=service_name='\''someother
  • runother '--vars=service_name=someother'

I tried putting double quotes around $2, removing single quotes like ${2//\'}, printing string as printf inside sub-bash.

UPD: Apparently programs consider ./a --b=c and ./a '--b=c' similarly, so the question has no meaning, and I had a bug in a different piece of code.

UPD2: As mentioned by @choroba in the comment below: "set -x adds quotes to the output so you can find how word splitting worked, they aren't actually added to the strings, though"

closed as off-topic by slm Jul 18 '18 at 11:06

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Questions describing a problem that can't be reproduced and seemingly went away on its own (or went away when a typo was fixed) are off-topic as they are unlikely to help future readers." – slm
If this question can be reworded to fit the rules in the help center, please edit the question.

  • 1
    Why the backslash before s? How do you verify that bash "puts single quotes around $2"? – choroba Jul 18 '18 at 0:19
  • @choroba you are right, no backslashes, but there are some forward slashes in the input too. I use set -x and when I do cmd=$(runother $2 | process output) I see + runother '--vars=service_name='\''someother .. in the console which does not work since runother expects --vars argument, not a large string. – Ben Usman Jul 18 '18 at 1:22
  • Oh, I found another bug, apparently even with '--var=' argument it still works. – Ben Usman Jul 18 '18 at 1:26
  • 2
    set -x adds quotes to the output so you can find how word splitting worked, they aren't actually added to the strings, though. – choroba Jul 18 '18 at 5:53
  • 1
    ./a --b=c and ./a '--b=c' aren't just similar, they identical from the running command's point of view. The shell removes the quotes as a standard part of processing. The issue you see with set -x is the usual issue when trying to output arbitrary strings to humans: there has to be some quoting since you may well have quotes in the actual string, so the output looks messy if you're not used to it. The args script in mywiki.wooledge.org/WordSplitting may be useful to visualize this sometimes, since it doesn't add fancy quoting. (It's ambiguous only if you have <> in the data.) – ilkkachu Jul 18 '18 at 9:53

Double quoting $2 (if that's where the value is) is the correct thing to do.

If you're looking at the output of set -x then be aware that the shell may well add various quoting in that output. Those extra quotes are not part of the data.

Example (in bash):

printf 'var has value %s\n' "$var"

This will output

var has value --vars=service_name='someothername'

but the set -x output will look as

$ set -x
$ var=--vars="service_name='someothername'"
+ var='--vars=service_name='\''someothername'\'''
$ printf 'var has value %s\n' "$var"
+ printf 'var has value %s\n' '--vars=service_name='\''someothername'\'''
var has value --vars=service_name='someothername'

In pdksh on OpenBSD:

$ set -x
$ var=--vars="service_name='someothername'"
+ var=--vars=service_name='someothername'
$ printf 'var has value %s\n' "$var"
+ printf var has value %s\n --vars=service_name='someothername'
var has value --vars=service_name='someothername'

In zsh:

$ set -x
$ var=--vars="service_name='someothername'"
+zsh:10> var='--vars=service_name='\''someothername'\'
$ printf 'var has value %s\n' "$var"
+zsh:11> printf 'var has value %s\n' '--vars=service_name='\''someothername'\'
var has value --vars=service_name='someothername'

Don't worry about this extra quoting in the debug output. Just use your variable with double quotes around it and you'll be fine.

  • what if I had multiple arguments in $@? Wouldn't putting double quotes around it make it seem like a "single string argument" whereas these are actually multiple string arguments? – Ben Usman Jul 18 '18 at 17:48
  • @BenUsman No, "$@" (note, quoted) is special in that sense that if you quote the expansion, it expands to all positional parameters, individually quoted. – Kusalananda Jul 18 '18 at 18:09

You should try to put a $ sign in front of your quoted parameter, while escaping the inner quotes, like this:

./run.sh name $'--vars="service_name=\'\someothername\'"'

That should work as the $ is telling the shell to consider the content of the string as a string so that it is not interpreted. And the quotes must be escaped to avoid being considered as ending quotes for the string.

(see also this post)

  • What if my string is stored in a variable I want to use inside sub-shell $(...)? I tried $$2, $${2}, \${${2}}, but they lead either to numerical values being substituted or '${--vars=service_name=. – Ben Usman Jul 18 '18 at 1:09
  • 1
    $'...' interprets backslash sequences. What do you mean by "to consider the content of the string as a string`? – choroba Jul 18 '18 at 5:52
  • $'--vars="service_name=\'someothername\'"' would indeed work if the idea is to have both the single and double quotes in the actual argument string. It probably isn't, though, it's somewhat rare to need that. (With only a few quotes, you might as well backslash them individually: --vars=\"service_name=\'someothername\'\".) I've no idea why you'd backslash the s, though. – ilkkachu Jul 18 '18 at 9:47

Not the answer you're looking for? Browse other questions tagged or ask your own question.