I have a main folder within which there are a number of folders, each containing a number of text files. I need to run a program on all of these text files. So far I have the following bash script which throws me a syntax error when I try to execute:
#!/bin/bash
for dir in mainfolder/*
for file in ${dir}/*.txt
do
echo “${file}”
./myprogram ${file}
done
done
The error I get is:
./myscript: line 5: syntax error near unexpected token for'
./myscript: line 5:for file in ${dir}/*.txt'
You forgot the first do.
#!bin/bash
for dir in mainfolder/*
do
for file in "${dir}"/*.txt
do
echo "${file}"
./myprogram "${file}"
done
done
Note the quotes around all variable references. As mentioned in comments, this is an important measure to take. Also keep in mind that quotes are " ", not “ ”.
This question already has answers here:
Are shell scripts sensitive to encoding and line endings?
(14 answers)
Closed 6 months ago.
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.
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
I was getting the same error on Cygwin; I did the following (one of them fixed it):
Converted TABS to SPACES
ran dos2unix on the .(ba)sh file
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
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'
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 ...)
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.
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
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.
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)
In my case, what was causing the problem was an if else statement. After re-writing the conditions, the error 'near done' got away.
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 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.
For me you had to have it do something between the do and done.
#!/bin/bash
echo "Endless Loop, to STOP press ctrl C or ctrl Z"
for ((; ;))
do
done
echo "Loop Ended"
gave me the error, but
#!/bin/bash
echo "Endless Loop, to STOP press ctrl C or ctrl Z"
for ((; ;))
do
sleep 1
done
echo "Loop Ended"
fixed it.
In a Makefile, I need to cycle through a list and write the current element of the list in a file.
The code is the following:
SHELL := /bin/bash
LIST = A B C
test:
for i in $(LIST) do \
echo $ii > file.txt \
done
I get the following error:
/bin/bash: -c: line 1: syntax error near unexpected token `>'
Do you know how to fix it?
You are missing a ; after $(LIST). You need to terminate the list of words you are giving to for before you can start the do block.
As indicated in the comments, you additionally need a : at the end of the echo line (the command that gets run has no newlines the way this works at the normal command line so you need to explicitly separate the commands from each other).
And further, to get the results you expect, you need to escape the $ in the shell command by using $$i (also pick one of $i or $ii as your variable name).
What is wrong with the 5th line in this script ( I have included the snippet that gives me the error and the actual error is listed in the bottom after the code and a link to complete script)?
#! /bin/bash
INSTALLDIR=/usr/local/mapguideopensource
CLEAN_FLAG=0
while [ $# -gt 0 ]; do # Until you run out of parameters...
case "$1" in
-prefix|--prefix)
INSTALLDIR="$2"
shift
;;
-clean|--clean)
CLEAN_FLAG=1
shift
;;
-help|--help)
echo "Usage: $0 (options)"
echo "Options:"
echo " --prefix [installation directory]"
echo " --clean [clean all objects and binaries in Oem]"
echo " --help [Display usage]"
exit
;;
esac
shift # Check next set of parameters.
done
This is the error i get when i run this bash script on linux (REHL5) :
: command not founde 4:
: command not founde 8:
: command not founde 8:
: command not founde 12:
MapGuide Open Source build script for OEM components
'/build_oem.sh: line 17: syntax error near unexpected token `in
'/build_oem.sh: line 17: ` case "$1" in
Please note, that the line number above corresponds to the actual script i am running (i have included a link to that script below)
The original script i am running
From the errors, I'm pretty sure you have carriage returns (aka CR or ^M) at the end of the lines. Windows/DOS text files have carriage return AND linefeed at the end of each line, but unix programs (like bash) just expect a linefeed, and get horribly confused if there's a CR as well. The giveaway is error messages like:
: command not founde 4:
What this really is is ./build_oem.sh: line 4: ^M: command not found, but the carriage return makes the terminal go back to the beginning of the line, and write the end of the message over the beginning of the message:
./build_oem.sh: line 4:
: command not found
|
V
: command not founde 4:
To fix the script, use dos2unix to convert it to proper unix format, then switch to a text editor that saves in unix format.
What choroba says, but also note that your shebang has to be on the first line (which it is not), otherwise it is useless since it's just a plain comment then and it won't necessarily execute under bash.
In the original script, lines 4 and 8 are empty. There is probably some invisible control character on the lines. Try xxd build_oem.sh.
for files in $(find . -maxdepth 1 -type f); do
echo $(basename $files)
done
Works when its copy/inserted into the console, but when ran as a shell script, it returns
'/TEST.sh: line 1: syntax error near unexpected token `do
'/TEST.sh: line 1: `for files in $(find . -maxdepth 1 -type f); do
EDIT:
Attempt 2 with #!/bin/sh added to the first line now results
-bash: /oper/text2pdf_TEST.sh: /bin/sh^M: bad interpreter: No such file or directory
However /bin/sh does exist
Attempt 3 with #!/bin/bash added to the first line now results
-bash: /oper/text2pdf_TEST.sh: /bin/bash^M: bad interpreter: No such file or directory
However /bin/bash does exist
Your error is the big hint: Notice that it wants to say
...near unexpected token `do'
but the closing tick is at the beginning of the line. That's because the token it's printing is do^M (do followed by a carriage return).
You probably edited the file in a DOS/Windows style editor. It needs to have UNIX style line endings.
Well, the error message says what's wrong:
/bin/sh^M: bad interpreter: No such file or directory
your editor puts an extra character ^M (code 13) after /bin/sh. Configure your editor so that it ends lines in the correct way.
It is also possible that you edit the file on an operating system which ends lines with CR+LF and then copy it over to an operating system which uses LF only. See this wikipedia article on some background on this newline confusion.
Without a shebang, your script is executed by /bin/sh. Depending on the system, sh might not support the $(...) syntax.
Add
#!/bin/bash
as the first line of the script.
#!/bin/sh
for files in $(find . -maxdepth 1 -type f); do
echo $(basename $files)
done
This one works fine for me. Maybe you forgot the Shebang (The first line specifying the interpreter)?