BASH Syntax error near unexpected token ‘done’ [duplicate]
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.
Your code is correct and works for me using ubuntu. Is the code above an exact copy-past? What does file file.sh output?
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?
@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.
13 Answers 13
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
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++.
This helped. I realized I had Windows line endings in the file and when I changed to Unix, the issue was solved.
For those who come across this question searching for the error message, other reasons that might cause the error messages are: ■ empty loop body ■ forget do ■ missing fi inside loop body ■
I was getting the same error on Cygwin; I did the following (one of them fixed it):
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 at the end of the file while Windows uses . That 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 and the nl stands for . 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:
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'
/shell-script: syntax error near unexpected token `done’
some general comments: You probably want to quote any filename variables that might possibly contain spaces.
5 Answers 5
you are closing the while before the if.
while read filename do echo "$filename" if [ -s $filename ] then tail -10 $filename | grep date '+%Y-%m-%d' >> $lastlines1 echo "- Next Error File - " >> $lastlines1 else echo " no errrors" fi done
Let’s add some new lines and indentation:
1 while read filename; do 2 echo "$filename" 3 if [ -s $filename ]; then 4 tail -10 $filename | grep date '+%Y-%m-%d' >> $lastlines1 5 echo "- Next Error File - " >> $lastlines1 6 done 7 else 8 echo " no errrors" 9 fi
lines 6 and 9 seem to be swapped. In other words the while-do-done and if-then-else-fi clauses are overlapping. Which is wrong in shell (and most other computer languages).
You need to use vim editor for scripting , it will shows text in RED if that syntax wrong
while read FileName do echo "$" if [ -s "$" ]; then tail -10 $FileName | grep "date '+%Y-%m-%d'" >> "$" echo "- Next Error File - " >> "$" else echo " no errrors" fi done
vim won’t magically fix code, just as another editor (except maybe nano without -w) won’t break it. It does make finding syntax errors easier though. Installing vim on some non-Linux systems can be quite annoying.
It depends a lot on the user’s environment. For a root user on a Linux system with internet access and a decent package manager, switching to vim is probably easy (if they can operate a vi-like editor). Not so much for a normal user on Solaris or a user on an embedded system with limited space.
You need to complete the if statement before the do while . If you are trying to only echo no errors once if no files are found, you need to use a flag to indicate it.
errorCount=0 while read filename do echo "$filename" if [ -s $filename ] then tail -10 $filename | grep date '+%Y-%m-%d' >> $lastlines1 echo "- Next Error File - " >> $lastlines1 errorCount=$(($errorCount + 1)) fi done if [[ $errorCount -eq 0 ]] then echo " no errors" fi
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 dos2unix or tr , for example:
This removes any CR characters from the file and in new shell script file you didn’t get that error.
You must log in to answer this question.
Related
Hot Network Questions
Subscribe to RSS
To subscribe to this RSS feed, copy and paste this URL into your RSS reader.
Site design / logo © 2023 Stack Exchange Inc; user contributions licensed under CC BY-SA . rev 2023.7.13.43531
Linux is a registered trademark of Linus Torvalds. UNIX is a registered trademark of The Open Group.
This site is not affiliated with Linus Torvalds or The Open Group in any way.
By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy.
Syntax error near unexpected token ‘done’
I have been writing a unix script that will scan through a text file, find instances of a specific word, and then delete a corresponding line in another document. Everything was working up until I went to test my most recent attempt, and I am getting:
./Present.sh: line 35: syntax error near unexpected token `done' ./Present.sh: line 35: ` done'
and I have no idea why. Googling the error gives me a few responses from unix.com, but nothing of value (trying the suggestions of others who had these problems did not help the problem). Thanks so much for the help. My code is:
for var in bent bound bled bred brought built burned burnt bought caught clung crept dealt dug dived dreamed dreamt fed felt fought found fled flung ground hung heard held kept knelt laid led leaped leapt learned learnt left lent lighted lost made meant met misspelled misspelt mowed mown paid pled proved proven sawed sawn said sought sold sent sewed sewn shaved shaven shone shoed shod shot showed sat slept slid slung sowed sown sped spent silted spilt spun sprung stood stuck stung struck strung swept swelled swollen swung taught told thought thrived understood upheld waved woven wept wound won withheld withstood wrung do cd ~ cd Documents/UPenn/'Senior Year'/'Spring 2011'/Thesis/Results/ echo "$var" NUMLINE=0 cat 'foradam.txt' | while IFS=$'\t' read -r word pos other; do if [ "$word" = '#' ] || [ "$word" = Number ] || [ "$word" = CHI ]; then NUMLINE=`expr $NUMLINE + 1` echo "error 1" echo "$word" echo "$NUMLINE" if [ "$word" = $var ] && [ "$pos" = VVN ];then sed -i '$NUMLINE' d Brown_Adam_CIVForms.txt echo "error 4" echo "$word" echo "$NUMLINE" else echo "nothing on this line" echo "$word" echo "$NUMLINE" fi done done
3 Answers 3
As it stands, your code is equivalent to:
for var in bent bound bled bred brought built burned burnt bought caught clung \ crept dealt dug dived dreamed dreamt fed felt fought found fled flung \ ground hung heard held kept knelt laid led leaped leapt learned learnt \ left lent lighted lost made meant met misspelled misspelt mowed mown \ paid pled proved proven sawed sawn said sought sold sent sewed sewn \ shaved shaven shone shoed shod shot showed sat slept slid slung sowed \ sown sped spent silted spilt spun sprung stood stuck stung struck \ strung swept swelled swollen swung taught told thought thrived \ understood upheld waved woven wept wound won withheld withstood wrung do cd ~ cd Documents/UPenn/'Senior Year'/'Spring 2011'/Thesis/Results/ echo "$var" NUMLINE=0 cat 'foradam.txt' | while IFS=$'\t' read -r word pos other; do if [ "$word" = '#' ] || [ "$word" = Number ] || [ "$word" = CHI ]; then NUMLINE=`expr $NUMLINE + 1` echo "error 1" echo "$word" echo "$NUMLINE" if [ "$word" = $var ] && [ "$pos" = VVN ];then sed -i '$NUMLINE' d Brown_Adam_CIVForms.txt echo "error 4" echo "$word" echo "$NUMLINE" else echo "nothing on this line" echo "$word" echo "$NUMLINE" fi fi # This fi is missing in your code. done done
There is a ‘ fi ‘ missing, which makes the ‘ done ‘ unexpected. An alternative diagnosis is that the nested ‘ if ‘ should actually be an ‘ elif ‘:
for var in bent bound bled bred brought built burned burnt bought caught clung \ crept dealt dug dived dreamed dreamt fed felt fought found fled flung \ ground hung heard held kept knelt laid led leaped leapt learned learnt \ left lent lighted lost made meant met misspelled misspelt mowed mown \ paid pled proved proven sawed sawn said sought sold sent sewed sewn \ shaved shaven shone shoed shod shot showed sat slept slid slung sowed \ sown sped spent silted spilt spun sprung stood stuck stung struck \ strung swept swelled swollen swung taught told thought thrived \ understood upheld waved woven wept wound won withheld withstood wrung do cd ~ cd Documents/UPenn/'Senior Year'/'Spring 2011'/Thesis/Results/ echo "$var" NUMLINE=0 cat 'foradam.txt' | while IFS=$'\t' read -r word pos other; do if [ "$word" = '#' ] || [ "$word" = Number ] || [ "$word" = CHI ]; then NUMLINE=`expr $NUMLINE + 1` echo "error 1" echo "$word" echo "$NUMLINE" elif [ "$word" = $var ] && [ "$pos" = VVN ]; then sed -i '$NUMLINE' d Brown_Adam_CIVForms.txt echo "error 4" echo "$word" echo "$NUMLINE" else echo "nothing on this line" echo "$word" echo "$NUMLINE" fi done done