0

Which of the following quoting styles, for GNU Bash variables, is preferred and why?

  1. Two double quotes: VAR="/path/$V1/path with space/$V2".
  2. Multiple double quotes: VAR=/path/"$V1"/"path with space"/"$V2".
  3. Combination: VAR="/path/"$V1"/path with space/"$V2"".
  4. Other.

Preferred here meaning, works as intended in as many cases as possible without being unnecessarily verbose, such that it can be used consistently without any issues. If there are (rare?) special cases, then please restrict it to filesystem paths.

Assume that the path part can contain spaces or special characters. For 2 this of course means that those path parts need to be quoted as well.

Basically this seems to boil down to another question: Does quoting the variable substitutions individually do something extra?

If this was true, then it would motivate 2 and 3 (to avoid having to quote each path part with space individually). If not, then 1 seems preferred since it is the simplest.

However, looking for example here, 2 is most common by far, though as a special case VAR="$OTHER_VAR"/path/to/something?

closed as primarily opinion-based by Thomas Dickey, Stephen Harris, Mr Shunz, X Tian, Rui F Ribeiro Feb 19 at 13:50

Many good questions generate some degree of opinion based on expert experience, but answers to this question will tend to be almost entirely based on opinions, rather than facts, references, or specific expertise. If this question can be reworded to fit the rules in the help center, please edit the question.

  • 3
    option 3 is out. the quotes do nothing. The choice of 1 or 2 is up to you. 1 is simpler. – ctrl-alt-delor Feb 18 at 20:18
  • 3
    see also unix.stackexchange.com/q/42847 for variable naming. – ctrl-alt-delor Feb 18 at 20:20
  • @ctrl-alt-delor For now it has mostly been predefined variable names, but I did not know about that convention, thanks! E.g., here both 1 and 2 are used: wiki.archlinux.org/index.php/XDG_Base_Directory . I have read a lot about double quotes here, but did not see much about how they work nested. If I understand you correctly, the nested (3) does nothing, and 1 and 2 are equivalent (always works the same) save for simplicity (less verbose)? Please feel free to expand this to an answer. Thanks! – Klorax Feb 18 at 20:27
  • @ctrl-alt-delor Added "paths with space" to the question that I forgot when I wrote it at first. It seems 1 is the preferred style, does it have any downsides? How come 2 is so common (due to so few paths having spaces?, e.g., VAR="$HOME"/path/to/something)? – Klorax Feb 18 at 20:52
  • 1
    Yes, option 1 just works in most cases. Downsides can occur when you need nested quoting where you have to escape another single quote or double quote. – Sergiy Kolodyazhnyy Feb 18 at 21:11
4

The main thing is: Double quote all strings that contain any form of expansion or whitespace, unless you know that you are allowed not to (see e.g. "When is double-quoting necessary?"). Whether you quote only the bits that actually needs quoting and leave the non-whitespace bits that are static outside of the quotes is less important.

I'll go through your options, one at a time:

  1. VAR="/path/$V1/path with space/$V2"

    This is by far the variation that is easiest to read (personal opinion). All the variable expansions are quoted and the string will not be split on the spaces (as it is quoted). I would use this option.

    The only thing to remember, as Sergiy Kolodyazhnyy pointed out in a comment, is that if the pathname contains an actual literal double quote character, this would have to be handled by either escaping it as \", or by temporarily terminating the double quoted string and inserting a " in a single quoted string, as in "this is a string with a "'"'" in it". Likewise, other characters that are special to the shell, like $ and \ and `, would need the same treatment within double quoted strings. Note that this is not an issue if a variable that is expanded in the pathname string contains one of these characters (that would be handled correctly).

  2. VAR=/path/"$V1"/"path with space"/"$V2"

    This (IMHO) looks a bit messy, but works. It double quotes all/most path components between the slashes. An alternative would possibly be to use single quotes where no variables are expanded:

    VAR=/'path'/"$V1"/'path with space'/"$V2"
    

Whether you use the second or the first option is down to you and your personal taste (or whatever convention your team uses on the project you're working on). I would suggest that you stay with a single convention and don't use a mix between the two, if possible.

There is no practical difference between the two "ways of quoting a pathname", apart from possibly that thing about pathnames that contain literal characters that are special to the shell (they would not be special inside single quotes), and the amount of quotation marks used.

You also mentioned

  • VAR="$OTHER_VAR"/path/to/something

    I see absolutely nothing wrong with this, and it is what I most commonly use when the rest of the path is static and contains no spaces. There is absolutely no difference between this and VAR="$OTHER_VAR/path/to/something".


The third option:

  1. VAR="/path/"$V1"/path with space/"$V2""

    Don't do this. Here, $V1 and $V2 are actually left unquoted since you terminate the double quoted bits around the variable expansions.

  • Awesome, thanks! If you have anything to append to the answer about the very common (I don't have any numbers) special case of 2, that I mention, such as motivations, pros, cons, and why not just move the second quote to the end to get 1, then I would be most grateful! – Klorax Feb 18 at 22:12
  • @Klorax Sorry, I forgot about that one. Let me type it up... – Kusalananda Feb 18 at 22:13
  • Though as long as this is an assignment, having the variables unquoted shouldn't break anything, so the third one is equivalent to the others. (It just looks silly and misleading.) – ilkkachu Feb 18 at 22:16
  • @ilkkachu I'm running with "quote every string that contains expansions" here. That helps later when they start appending export to the start of the line... – Kusalananda Feb 18 at 22:20
1

Preferred here meaning, works as intended in as many cases as possible without being unnecessarily verbose,

Then use the first one. The others have unneeded quote characters. You only need two.

If you have lots of characters that have special meanings inside double quotes, i.e. $, \, " or `, then all the required escaping can get ugly. But filenames and paths don't contain those that often.

Does quoting the variable substitutions individually do something extra?

No, except that "$foo"bar is the same as "${foo}bar". That is, you can use the quotes instead of the braces to terminate the variable name. ("$foobar" would of course be totally different.)

1

The first option looks preferable, but (unfortunately?) does not work for pathname expansion as bash manual clearly states:

A variable may be assigned to by a statement of the form

    name=[value]

All values undergo tilde expansion, parameter and variable expansion, command substitution, arithmetic expansion, and quote removal. (...)

Pathname expansion is not performed.

One essential example is the tilde expansion:

var=~/"path/to/dir"       # tilde is expanded to user's home directory
var="~/path/to/dir"       # literal string is substituted

What's interesting globbing mechanism does work with or without double quotes in bash (that's not true for zsh with default settings).

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