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).

  • 1
    No, this is the whole code. Newlines are 0a. – knezi Jun 20 '16 at 9:54
  • 2
    @Rahul the hexadecimal code of the Unix linefeed character – PSkocik Jun 20 '16 at 9:57
  • 2
    Is the $BASH_ENV set? – roaima Jun 20 '16 at 10:36
  • 2
    @PSkocik that is really weird. bash -c "source /tmp/test" works. – knezi Jun 20 '16 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 '16 at 10:45
up vote 73 down vote accepted

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.

  • 16
    You are completely right. I have set: alias fi='find -type f | xargs grep -H '. – knezi Jun 20 '16 at 11:09
  • 7
    Get rid of that alias now! :) – Mark Stewart Jun 21 '16 at 1:47
  • 8
    I am astounded that anybody managed to figure out such an obscure problem. Well done, sir. – MathematicalOrchid Jun 21 '16 at 9:53
  • 4
    @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 '16 at 11:18

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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