Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

This question already has an answer here:

I have some bash scripts, one which has the following content:

#!/bin/bash
source $(dirname ${BASH_SOURCE[0]})/script.sh

while the other one has the following content:

#!/bin/bash
source "$(dirname ${BASH_SOURCE[0]})/script.sh"

How do these scripts behave differently and why? What is the difference?

share|improve this question

marked as duplicate by Gilles, jasonwryan, slm, Anthon, Zelda Apr 15 at 15:38

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

3 Answers 3

up vote 6 down vote accepted

The main difference is that the quoted version is not subject to field splitting by the shell.

With double quotes the outcome of the command expansion would be fed as one parameter to the source command. Without quotes it would be broken up into multiple parameters, depending on the value of IFS which contains space, TAB and newline by default.

If the directory name does not contain such spaces then field splitting does not occur.

As a rule of thumb, it is best to use double quotes with command substitutions and variable expansions.

share|improve this answer

Without quotes the string is subject to word splitting and globbing. See also BashPitfalls #14.

Compare

$ echo $(printf 'foo\nbar\nquux\n*')
foo bar quux ssh-13yzvBMwVYgn ssh-3JIxkphQ07Ei ssh-6YC5dbnk1wOc 

with

$ echo "$(printf 'foo\nbar\nquux\n*')"
foo
bar
quux
*

When word splitting occurs the first character of IFS acts as a separator (which, per default, is a space).

In almost all situations you want to add quotes. There are a few exceptions, e.g.

  • In expressions where word splitting/globbing does not occur, for example simple (non-array) assignments and the case statement. The following are all safe:

    • foo=*
    • foo=${bar}qux${quux}
    • foo=$(bar "${quux}")
    • case ${var} in

    This, however, is not (if what you are after is a single element with a literal asterisk character):

    • foo=( * )
  • When you specifically want word splitting to occur, e.g. looping over the tokens in a whitespace-delimited string (with globbing disabled). However - if possible, use an array.

share|improve this answer
2  
+1 For mentioning globbing. This bit me more than once. –  helpermethod Apr 14 at 14:10

The likely most important difference would be if the directory that the script is in has a space in it. In that case, the first line, the one without the double-quotes, would fail. This would be the result of "word splitting" which bash does on unquoted strings.

Suppose that the result of dirname ${BASH_SOURCE[0]} is /home/j r/bin. Consider the line without quotes:

source $(dirname ${BASH_SOURCE[0]})/script.sh

In this case, bash will see the command:

source /home/j r/bin/script.sh

After word splitting, the source command sees a script name, /home/j and an argument to the script, r/bin/script.sh. Very likely, there is no script by that name and bash will return the error message:

bash: /bin/j: No such file or directory

Now consider what happens with double quotes:

source "$(dirname ${BASH_SOURCE[0]})/script.sh"

In this case, the source command will look for a script named /home/j r/bin/script.sh and try to source it.

For completeness, let's consider single-quotes:

source '$(dirname ${BASH_SOURCE[0]})/script.sh'

In this case, unlike the previous two, dirname is never executed. The source command will try to source a command with the literal name $(dirname ${BASH_SOURCE[0]})/script.sh. There is likely no such file and bash will emit an error message.

How bash treats strings in double quotes is described in full detail in man bash:

  Enclosing characters in double quotes preserves the  literal  value  of
   all  characters  within the quotes, with the exception of $, `, \, and,
   when history expansion is enabled, !.  The characters $  and  `  retain
   their  special meaning within double quotes.  The backslash retains its
   special meaning only when followed by one of the following  characters:
   $,  `,  ", \, or <newline>.  A double quote may be quoted within double
   quotes by preceding it with a backslash.  If enabled, history expansion
   will  be  performed  unless an !  appearing in double quotes is escaped
   using a backslash.  The backslash preceding the !  is not removed.
share|improve this answer

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