28

I have the following script:

#!/bin/bash
set -x
if :; then
    echo a
fi

If I run bash /tmp/file, a is echoed, but if I run source /tmp/file, I get:

bash: /tmp/test: line 6: syntax error: unexpected end of file

The output:

knezi@holly tmp]$set -x; source /tmp/test; set +x
+ source /tmp/test
++ set -x
bash: /tmp/test: line 6: syntax error: unexpected end of file
+ set +x

knezi@holly tmp]$set -x; command source /tmp/test; set +x
+ set -x
+ command source /tmp/test
+ source /tmp/test
++ set -x
bash: /tmp/test: line 6: syntax error: unexpected end of file
+ set +x

knezi@holly tmp]$bash -c "source /tmp/test"
+ bash -c 'source /tmp/test'
++ :
++ echo a
a


knezi@holly tmp]$od -c /tmp/test
0000000   #   !   /   b   i   n   /   b   a   s   h  \n   s   e   t    
0000020   -   x  \n   i   f       :   ;       t   h   e   n  \n  \t   e
0000040   c   h   o       a  \n   f   i  \n
0000051

Output of commands shopt -p and set -o: http://pastebin.com/bsqc8aru

Output of set: http://pastebin.com/S9KpqZAL

declare -fp produces nothing.

I thought that source does the same as bash, but instead of starting new session rather runs the code in the current one. Can anyone explain this error to me?

I run bash GNU bash, version 4.2.53(1)-release (x86_64-redhat-linux-gnu).

15
  • 1
    No, this is the whole code. Newlines are 0a.
    – knezi
    Jun 20, 2016 at 9:54
  • 2
    @Rahul the hexadecimal code of the Unix linefeed character
    – PSkocik
    Jun 20, 2016 at 9:57
  • 2
    Is the $BASH_ENV set?
    – roaima
    Jun 20, 2016 at 10:36
  • 2
    @PSkocik that is really weird. bash -c "source /tmp/test" works.
    – knezi
    Jun 20, 2016 at 10:42
  • 5
    Ah-ha! Please add that it works with bash -c to your question. Then, show us the contents of your ~/.bashrc file, there's probably something there that's screwing things up.
    – terdon
    Jun 20, 2016 at 10:45

1 Answer 1

78

I can reproduce your behaviour if I alias fi:

$ alias fi=:
+ alias fi=:
$ . ./test
+ . ./test
++ set -x
bash: ./test: line 6: syntax error: unexpected end of file

It works when you execute it but fails when you source it because aliases are not available in non-interactive shells (the type of shell that runs shell scripts). As explained in the bash manual:

Aliases are not expanded when the shell is not interactive, unless the expand_aliases shell option is set using shopt (see The Shopt Builtin).

However, when you source something, it is run in your current shell which, because it is interactive, has already loaded the aliases and therefore the fi alias is recognized and breaks the sourcing.

4
  • 16
    You are completely right. I have set: alias fi='find -type f | xargs grep -H '.
    – knezi
    Jun 20, 2016 at 11:09
  • 7
    Get rid of that alias now! :) Jun 21, 2016 at 1:47
  • 9
    I am astounded that anybody managed to figure out such an obscure problem. Well done, sir. Jun 21, 2016 at 9:53
  • 6
    @MathematicalOrchid I suspected that something was aliased (because of the interactive shell), set was ruled out by the output, and alias if='foo "' (a trailing open quote gave an error about the missing quote, and so the last option was aliasing fi.
    – muru
    Jun 21, 2016 at 11:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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