28

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.

user1837725
  • 343
  • 1
  • 3
  • 8
  • 1
    Your code is correct and works for me using ubuntu. Is the code above an exact copy-past? What does `file file.sh` output? – Fredrik Pihl Aug 21 '13 at 21:20
  • 2
    What is the problem? Does it run but not work right? Does it not run at all? Does it give you some message? Do paisley ponies parade around your kitchen? – twalberg Aug 21 '13 at 21:22
  • 3
    @twalberg: The error message (I presume) is in the title. – Keith Thompson Aug 21 '13 at 21:34
  • How did you type your code? Run `od -bc` on your source file and paste the output in your question. – anubhava Aug 21 '13 at 21:37
  • @KeithThompson You're right that there is an error message referenced in the title, but the posted code does not evoke that message, which renders the exact situation and question a bit unclear... – twalberg Aug 21 '13 at 22:17
  • Try this: http://unix.stackexchange.com/questions/225055/while-read-line-do-cause-syntax-error-near-unexpected-token-done-in-linux Worked fine for me. – Damitha May 02 '16 at 15:49

12 Answers12

39

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
that other guy
  • 101,688
  • 11
  • 135
  • 166
  • Just to add to this - there's a bug in Notepad++ that continues to insert `\r\n` after the file has been converted to `\n`, if the conversion was done outside Notepad++. – rustyx Jan 08 '21 at 13:03
11

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
Kunal B.
  • 513
  • 6
  • 21
6

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
David W.
  • 98,713
  • 36
  • 205
  • 318
4

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.

Mihit Gandhi
  • 125
  • 10
3

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

sauna-l
  • 31
  • 2
3

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'
charliegreen
  • 446
  • 1
  • 4
  • 11
  • I know this doesn't strictly answer the question asked, but since this is the first google result for "bash syntax error near unexpected token done", I imagine this will still be useful to some people. – charliegreen Oct 17 '16 at 03:31
  • this helped me realize I should replace double quotes `"` with single quotes `'` to avoid bash doing something with the quoted exclamation marks `echo "!! ok"` --> `echo '!! ok'` – Rafa Jun 21 '20 at 13:05
  • why would I be experiencing this exact same problem but I don't have any backticks inside double-quotes? I have this for loop: for (( i=1; i<=FULL_SIZE_CHUNKS; i++ )); do send_chunk ${i} '{"P":"1"}' SKIP=$(( READ_COUNT + SKIP )) READ_COUNT=$(( CHUNK_SIZE - 34 )) done – m4l490n Oct 16 '20 at 17:49
2

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
justbrowsing
  • 129
  • 4
1

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.

lampShadesDrifter
  • 3,103
  • 3
  • 21
  • 66
1

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)

Yohei
  • 1,241
  • 6
  • 28
0

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.

santy
  • 131
  • 1
  • 11
0

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.

Benjamin W.
  • 33,075
  • 16
  • 78
  • 86
jak
  • 353
  • 1
  • 4
  • 9
0

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

Esteban
  • 1
  • 3