7

I have a simple shell script I copied from a working script. It works if I copy-paste it to a terminal:

if true
then
  true
fi 

However, when I run the script with bash myscript, I get various syntax errors as if some of the keywords are missing.

  • myscript: line 4: syntax error near unexpected token `fi' , as if then isn't there.
  • myscript: line 6: syntax error: unexpected end of file , as if fi isn't there.
  • myscript: line 4: syntax error near unexpected token `$'\r' .. what?

Why does this happen in this particular script, but not on my command line or in the script I copied from?

that other guy
  • 116,971
  • 11
  • 170
  • 194
  • 1
    Consider adding http://www.shellcheck.net/ to your automated testing workflow. – kojiro Aug 07 '15 at 20:31
  • Is there a Windows machine in the vicinity of the code? Could there be carriage returns in the non-working version? One of the errors uses ```$'\r'``` which suggests this is the problem. See [How to convert DOS/Windows newline (CRLF) to Unix newline (\n) in bash script?](http://stackoverflow.com/questions/2613800/) amongst many other relevant questions. – Jonathan Leffler Aug 07 '15 at 20:32
  • @JonathanLeffler Yes, I fabricated this question and gave a community answer because I'm never able to find a general question for marking as duplicate. For example, the one you suggest is about how to convert a file and it would not be obvious to a poster why that's at all relevant. I've added this one to the bash tag wiki, but if you find a better one I'm happy to switch it. – that other guy Aug 07 '15 at 20:36
  • It's been asked so many times that it is surprising that you failed to find useful information. Here are a couple [1](http://stackoverflow.com/questions/20895946/syntax-error-near-unexpected-token-bash), [2](http://stackoverflow.com/questions/31886144/why-is-a-shell-script-giving-syntax-errors-when-the-same-code-works-elsewhere) – Thomas Dickey Aug 08 '15 at 11:30
  • @ThomasDickey If you update the bash tag wiki with any question you'd think make a better, general, canonical FAQ for deduping syntax errors due to CR, I'll be absolutely delighted to delete this question! (Finding good ones are tricky, as evidenced by your #2 being this very post.) – that other guy Aug 08 '15 at 16:57
  • Sorry for the poor example. Here are a few more: [1](http://www.itforeveryone.co.uk/shellProgramming.html), [2](http://www.linuxquestions.org/questions/linux-general-1/bad-interpreter-no-such-file-or-directory-213617/), [3](http://askubuntu.com/questions/304999/not-able-to-execute-a-sh-file-bin-bashm-bad-interpreter). "bad interpreter" seems to find the most comments (and answers). The issue's been around (and well-known) for 10-15 years. So a *good* answer would collect and summarize the more useful ones. – Thomas Dickey Aug 08 '15 at 17:13
  • @ThomasDickey It's easy to find a duplicate answer, the hard part is finding a duplicate question -- I wanted to avoid marking questions about "unexpected end of file" as duplicates of "bad interpretter" as this would seem confusing. I don't disagree though, and I'll support any question and/or answer you find/edit/post. I just want a canonical question to dedupe with. – that other guy Aug 08 '15 at 17:34

1 Answers1

17

TL;DR: Your script has Windows style CRLF line endings, aka \r\n.

Convert to Unix style \n by deleting the carriage returns.


How do I check if my script has carriage returns?

They're detectable as ^M in the output of cat -v yourscript:

$ cat -v myscript
if true^M
then^M
  true^M
...

How do I remove them?

Set your editor to save the file with Unix line endings, aka "line terminators" or "end-of-line characters", and resave it.

You can also remove them from a command line with dos2unix yourscript or cat yourscript | tr -d '\r' > fixedscript.

Why do carriage returns cause syntax errors?

The carriage return character is just another character to bash. then is not the same as then\r, so bash doesn't recognize it as a keyword and assumes it's a command. It then keeps looking for a then and fails

If there happens to be a trailing space after then, you get a similar problem for fi.

that other guy
  • 116,971
  • 11
  • 170
  • 194