8

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?

7
  • 1
    Consider adding shellcheck.net to your automated testing workflow. Commented Aug 7, 2015 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? amongst many other relevant questions. Commented Aug 7, 2015 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. Commented Aug 7, 2015 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, 2 Commented Aug 8, 2015 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.) Commented Aug 8, 2015 at 16:57

1 Answer 1

19

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.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.