[bash] BASH Syntax error near unexpected token 'done'

Any idea of what the problem could be?

My code is:

#!/bin/bash
while :
do
echo "Press [CTRL+C] to stop.."
sleep 1
done

Saved it as .sh and ran bash file.sh

CentOS 6 32-bit

What is the issue? First time EVER using BASH, need it for a simple infinite loop on something.

This question is related to bash

The answer is


Edit your code in any linux environment then you won't face this problem. If edit in windows notepad any space take it as ^M.


I had same problem, but solved.

I removed the following line in .bashrc

alias do="docker.exe" # this line caused the problem

I use WSL(windows subsystem for linux)


Sometimes this error happens because of unexpected CR characters in file, usually because the file was generated on a Windows system which uses CR line endings. You can fix this by running os2unix or tr, for example:

tr -d '\015' < yourscript.sh > newscript.sh

This removes any CR characters from the file.


In my case, what was causing the problem was an if else statement. After re-writing the conditions, the error 'near done' got away.


Had similar problems just now and these are two separate instances and solutions that worked for me:

Case 1. Basically, had a space after the last command within my newline-separated for-loop, eg. (imagining that | here represents the carat in a text editor showing where you are writing), this is what I saw when clicking around the end of the line of the last command in the loop:

for f in $pathToFiles
do
   $stuff |
done

Notice the space before before the carat (so far as I know, this is something cat has no option do display visually (one way you could test is with something like od -bc yourscript.sh)). Changing the code to

for f in $pathToFiles
do
   $stuff| <--- notice the carat shows no ending space before the newline
done

fixed the problem.

Case 2. Was using a pseudo try-catch block for the for-loop (see https://stackoverflow.com/a/22010339/8236733) like

{
for f in $pathToFiles
do
   { $stuff } || { echo "Failed to complete stuff"; exit 255; }
done
} || { echo "Failed to complete loop"; exit 255; }

and apparently bash did not like the nested {}s. Changing to

{
for f in $pathToFiles
do
   $stuff
done
} || { echo "Failed to complete loop"; exit 255; }

fixed the problem in this case. If anyone can further explain either of these cases, please let me know more about them in the comments.


There's a way you can get this problem without having mixed newline problems (at least, in my shell, which is GNU bash v4.3.30):

#!/bin/bash
# foo.sh

function foo() {
    echo "I am quoting a thing `$1' inside a function."
}

while [ "$input" != "y" ]; do
    read -p "Hit `y' to continue: " -n 1 input
    echo
done

foo "What could possibly go wrong?"
$ ./foo.sh
./foo.sh: line 11: syntax error near unexpected token `done'
./foo.sh: line 11: `done'

This is because bash expands backticks inside double-quoted strings (see the bash manual on quoting and command substitution), and before finding a matching backtick, will interpret any additional double quotes as part of the command substitution:

$ echo "Command substitution happens inside double-quoted strings: `ls`"
Command substitution happens inside double-quoted strings: foo.sh
$ echo "..even with double quotes: `grep -E "^foo|wrong" foo.sh`"
..even with double quotes: foo "What could possibly go wrong?"

You can get around this by escaping the backticks in your string with a backslash, or by using a single-quoted string.

I'm not really sure why this only gives the one error message, but I think it has to do with the function definition:

#!/bin/bash
# a.sh

function a() {
    echo "Thing's `quoted'"
}
a
while true; do
    echo "Other `quote'"
done
#!/bin/bash
# b.sh

echo "Thing's `quoted'"
while true; do
    echo "Other `quote'"
done
$ ./a.sh
./a.sh: line 10: syntax error near unexpected token `done'
./a.sh: line 10: `done'
$ ./b.sh
./b.sh: command substitution: line 6: unexpected EOF while looking for matching `''
./b.sh: command substitution: line 9: syntax error: unexpected end of file
Thing's quote'
./b.sh: line 7: syntax error near unexpected token `done'
./b.sh: line 7: `done'

Run cat -v file.sh.

You most likely have a carriage return or no-break space in your file. cat -v will show them as ^M and M-BM- or M- respectively. It will similarly show any other strange characters you might have gotten into your file.

Remove the Windows line breaks with

tr -d '\r' < file.sh > fixedfile.sh

Open new file named foobar

nano -w foobar

Input script

 #!/bin/bash
 while [ 0 = 0 ]; do
   echo "Press [CTRL+C] to stop.."
   sleep 1
 done;

Exit and save

CTRL+X then Y and Enter

Set script executable and run

chmod +x foobar
./foobar

What is the error you're getting?

$ bash file.sh
test.sh: line 8: syntax error: unexpected end of file

If you get that error, you may have bad line endings. Unix uses <LF> at the end of the file while Windows uses <CR><LF>. That <CR> character gets interpreted as a character.

You can use od -a test.sh to see the invisible characters in the file.

$ od -a test.sh
0000000    #   !   /   b   i   n   /   b   a   s   h  cr  nl   #  sp  cr
0000020   nl   w   h   i   l   e  sp   :  cr  nl   d   o  cr  nl  sp  sp
0000040   sp  sp   e   c   h   o  sp   "   P   r   e   s   s  sp   [   C
0000060    T   R   L   +   C   ]  sp   t   o  sp   s   t   o   p   "  cr
0000100   nl  sp  sp  sp  sp   s   l   e   e   p  sp   1  cr  nl   d   o
0000120    n   e  cr  nl                                                
0000124

The sp stands for space, the ht stands for tab, the cr stands for <CR> and the nl stands for <LF>. Note that all of the lines end with cr followed by a nl character.

You can also use cat -v test.sh if your cat command takes the -v parameter.

If you have dos2unix on your box, you can use that command to fix your file:

$ dos2unix test.sh

I was getting the same error on Cygwin; I did the following (one of them fixed it):

  1. Converted TABS to SPACES
  2. ran dos2unix on the .(ba)sh file

Might help someone else : I encountered the same kind of issues while I had done some "copy-paste" from a side Microsoft Word document, where I took notes, to my shell script(s).

Re-writing, manually, the exact same code in the script just solved this.

It was quite un-understandable at first, I think Word's hidden characters and/or formatting were the issue. Obvious but not see-able ... I lost about one hour on this (I'm no shell expert, as you might guess ...)


I have exactly the same issue as above, and took me the whole day to discover that it doesn't like my newline approach. Instead I reused the same code with semi-colon approach instead. For example my initial code using the newline (which threw the same error as yours):

Y=1
while test "$Y" -le "20"
do
        echo "Number $Y"
        Y=$[Y+1]
done

And using code with semicolon approach with worked wonder:

Y=1 ; while test "$Y" -le "20"; do echo "Number $Y"; Y=$[Y+1] ; done

I notice the same problem occurs for other commands as well using the newline approach, so I think I am gonna stick to using semicolon for my future code.