18

I have been told that the spaces are important in bash or other shell scripts and I should not change the existence of spaces unless I know what I am doing. By "changing the existence" I mean either inserting a space between two non-space characters or removing a space between two non-space characters, e.g. changing var="$val" to var ="$val" or vice versa. I want to ask

Are there any cases in which using a single space or using multiple consecutive spaces in a shell script makes a difference?.

(Of course, inserting/deleting a space in quotes makes a difference ,like changing from echo "a b" to echo "a b" or vice versa. I am looking for examples other than this trivial example.)

I have come across this question but that one is about adding and removing spaces between two non-space characters for which I know many examples that it would make a difference.

Any help would be appreciated. Include more varieties of shells if possible.

0

5 Answers 5

25

This is probably cheating, but this:

rm foo\ bar         # "delete the file named 'foo bar'"

is different from this:

rm foo\  bar        # "delete the files named 'foo ' and 'bar'"

even though the spaces are not in quotes. ;-)

More confoundingly, this:

rm \
    foo          # "delete the file named 'foo'"

is different from this:

rm \ 
    foo          # "delete the file named ' ', then run the command 'foo'"

even though they look identical!

1
  • Even though the spaces are not in quotes, the backslash is functionally similar to form of quoting and I'd put this in the same category as the question's "trivial example". (It is interesting though.)
    – David Z
    Commented Dec 29, 2017 at 23:22
23

Outside of quotes, the shell uses whitespace (spaces, tabs, newline, carriage-return, etc) as a word/token separator. That means:

  • Things not separated by whitespace are considered to be one "word".
  • Things separated by one-or-more whitespace characters are considered to be two (or more) words.

The actual number of whitespace chars between each "thing" doesn't matter, as long as there is at least one.

5
  • Thank you. I can't find any counter example myself. I just want to make sure. Commented Dec 29, 2017 at 2:55
  • 2
    Bash also considers form feeds and vertical tabs to be whitespace.
    – fpmurphy
    Commented Dec 29, 2017 at 4:08
  • true. i originally wrote '...newlines, etc' and then changed it to explicitly add carriage-returns. accidentally dropped the 'etc'.
    – cas
    Commented Dec 29, 2017 at 5:03
  • What if the number of spaces is so large, that the program cannot fit into memory? Commented Dec 29, 2017 at 10:18
  • 10
    @Worse_Username The whitespace does not have to fit in memory. I just created a 48GB script on a machine with 8GB of RAM and 20GB of swap. It ran just fine. It did take 3 minutes to crunch through all of that whitespace, but in the end it successfully ran an echo command with that much whitespace between the command and the argument.
    – kasperd
    Commented Dec 29, 2017 at 11:59
14

If we don't talk about the space character (U+0020), but any whitespace character (U+0020, \n, \t, etc.), then one particular case come to my mind: Here-Documents.

This code (using spaces):

cat <<- 'EOF'
<space><space>foo
EOF

Will print:

  foo

But this code (using tabs):

cat <<- 'EOF'
<tab><tab>foo
EOF

Will print:

foo

That's because (as POSIX states):

If the redirection operator is <<-, all leading <tab> characters shall be stripped from input lines and the line containing the trailing delimiter.

3
  • 1
    That is interesting. I thought about here-documents but did not know the <<- operator. Thank you very much. Commented Dec 29, 2017 at 3:48
  • here documents are a form of quoted text, not shell code. shell word-splitting doesn't apply.
    – cas
    Commented Dec 29, 2017 at 5:07
  • @cas Your comment is correct, but I don't think that the OP restricted their question to shell word-splitting. While word-splitting explains everything that word-splitting does (which is a LOT), I think that this is a good additional answer to the question, "Are there any cases in which using a single space or using multiple consecutive spaces in a shell script makes a difference?"
    – chris
    Commented Nov 27, 2022 at 19:54
3

It also has an effect when writing assignment statements. Like if I say FOO=xyz it will create an environment variable named FOO with value xyz, but if I separate the equals with a space, it will think that I'm invoking a program named FOO with the arg =xyz. So it does matter when it comes to certain syntax.

1
  • Usually FOO=xyz does create an internal shell variable but not an environment variable. You need set -a or export FOO=xyz for that (i.e. making it part of the environment of non-subshell subprocesses). Commented Dec 30, 2017 at 15:30
1

I came across a good example of 'space' and thought of sharing here. The following condition doesn't evaluate to true for i being somewhere between 100 and 1000.

if [ $i -ge 100 -a $i -lt 1000]; then  <some code here>  fi

Notice a missing space between 1000 and closing square bracket

But when it is changed to as mentioned below, it works as expected.

>  if [ $i -ge 100 -a $i -lt 1000 ]; then  <some code here>  fi
3
  • Yes, changing from no space to one or more spaces obviously matters, like e.g. cas's answer above mentions. The test [ ... ] is a regular command, so this is in principle same as cp foo bar vs. cp foobar.
    – ilkkachu
    Commented Mar 25, 2020 at 17:19
  • @ilkkachu True, But it's not so intutive in the case I mentioned and what is being mentioned for cp foo bar versus cp foobar
    – Maneesh
    Commented Mar 25, 2020 at 17:40
  • I agree with you, @Maneesh. I think that everybody makes this mistake at least once with [ or [[. I think that it also happens with arithmetic evaluations like echo $(( 3 + 2 )). There are so many languages where it is considered good style to not have spaces inside square braces and parentheses that this can really catch people off guard.
    – chris
    Commented Nov 27, 2022 at 19:58

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .