zsh: event not found: /bin/bash -- syntax error - bash

file.sh
#!/bin/bash
if { true }
then echo "hi"
fi
I have this within a shell-script. Upon trying to run, I get:
% ./file.sh
./brackets.sh: line 4: syntax error near unexpected token `then'
./brackets.sh: line 4: `then echo "hi"'
Running in my shell:
% #!/bin/bash
if { true }
then echo "hi"
fi
zsh: event not found: /bin/bash
Running again in my shell:
% if { true }
then echo "hi"
fi
hi
so the issue is with !/bin/bash. Anyone know what's going on? I looked online but all the posts on it are far in the past and it seems like the users weren't doing this inside a file/shellscript.
I am on MacOS Ventura, running zsh.
To be clear, I'm not asking you to fix my program. I'm just curious what's wrong with it as is, for learning purposes. I'm using {} because I was messing with the exit statuses.

If you are using zsh instead of bash, you can start your file with:
#!/bin/zsh
Also, there is no need for curly braces around true. So this should work:
#!/bin/zsh
if true
then echo "hi"
fi
Note that you can also run the above file with bash.
bash file.sh

Related

Syntax error when running bash script in Homestead Vagrant

I'm trying to run a script in Vagrant (vagrant ssh), however I am getting the error below:
tests/unit/runTests.sh: 4: tests/unit/runTests.sh: Syntax error: "(" unexpected
Command: sh tests/unit/runTests.sh
The script runs fine outside for vagrant and the only script info I've been able to find about vagrant are related to provisions, which is not what I'm doing in this case.
Script:
#!/bin/bash
i=0
fails=()
for d in tests/unit/*/ ; do
eval "vendor/bin/peridot -c tests/unit/peridot.php $d"
if [ $? -eq 1 ]
then
fails[$i]=$d
fi
wait
done
for ((j=0; j < ${#fails[#]}; j++)) do
echo "${fails[$j]}"
done
I've read about "(" syntax errors being related to dash, but I am using the suggestions that those posts had (#!/bin/bash).
Thanks for any suggestions.
Command: sh tests/unit/runTests.sh
It means that you (vagrant) is trying to run your script in 'sh', not in 'bash'. In this case, the first line (#!/bin/bash) is ignored and 'sh' interpret doesn't expect '(' character.

Executing a shell script from a file

My OS platform is this : SunOS machinehull01 5.10 Generic_148888-05 sun4v sparc SUNW,Sun-Fire-T200
I have written a shell script to run from a file
File name: test.sh
#!/bin/sh
VARNAME=$grep '-l' TestWord /home/hull/xml/text/*.txt
echo "Found $VARNAME"
When I run the above command in the console I'm getting the correct output without errors, But when I run sh test.sh or ./test.sh I'm getting below error
test.sh: -l: not found
Found
Can someone please help me on this?
You are searching for so called "command substitution" :
VARNAME=$(grep -l TestWord /home/hull/xml/text/*.txt)
echo "Found $VARNAME"
It will execute the command between $( and the closing parenthesis ) in a subshell and return the output of the command into VARNAME.
Got it.
#!/bin/sh
VARNAME=`grep -l TestWord /home/hull/xml/text/*.txt`
echo "Found $VARNAME"
I had to put those (`)there.

How to check the current shell and change it to bash via script?

#!/bin/bash
if [ ! -f readexportfile ]; then
echo "readexportfile does not exist"
exit 0
fi
The above is part of my script. When the current shell is /bin/csh my script fails with the following error:
If: Expression Syntax
Then: Command not found
If I run bash and then run my script, it runs fine(as expected).
So the question is: If there is any way that myscript can change the current shell and then interpretate rest of the code.
PS: If i keep bash in my script, it changes the current shell and rest of the code in script doesn't get executed.
The other replies are correct, however, to answer your question, this should do the trick:
[[ $(basename $SHELL) = 'bash' ]] || exec /bin/bash
The exec builtin replaces the current shell with the given command (in this case, /bin/bash).
You can use SHEBANG(#!) to overcome your issue.
In your code you are already using she-bang but make sure it is first and foremost line.
$ cat test.sh
#!/bin/bash
if [ ! -f readexportfile ]; then
echo "readexportfile does not exist"
exit 0
else
echo "No File"
fi
$ ./test.sh
readexportfile does not exist
$ echo $SHELL
/bin/tcsh
In the above code even though I am using CSH that code executed as we mentioned shebang in the code. In case if there is no shebang then it will take the help of shell in which you are already logged in.
In you case you also check the location of bash interpreter using
$ which bash
or
$ cat /etc/shells |grep bash

shell script comparing two variables

I have created a script for updating some ipaddress in iptables. Hereby I'm describing the issues which I'm facing with that.
Issues:
Comparison not happening between two variables within a script
At the end of script i need to execute a command ie; service restart/stop etc and output of the commands should be visible while executing the script.
1) Here am comparing two variable strings:
BASE=172.31.0.0
CMD=172.31.1.0
if [[ "$CMD" == "$BASE" ]]; then
echo "ip are same"
else
echo "not matched"
fi
but there is no response/output while executing the above script. Here its not comparison is not happening..Kindly suggest a best solution to resolve this issue.
2) after executing the script I need to restart the iptables:
BASE=172.31.0.0
CMD=172.31.1.0
if [[ "$CMD" == "$BASE" ]]; then
echo "ip are same"
else
echo "not matched"
fi
service iptables restart
iptables -nvL
A script should display the output of the last two lines (commands). Kindly suggest me the best solution and how to do this in a best way.
That's very odd. This should work, so if it's not working you forgot to mention something important.
How is this script being executed? Do you simply type ./script or is it executed by some service (like cron)?
Here are some of suggestions to debug:
Sanity check: see if bash works (perhaps your login shell isn't bash, so you didn't notice). Run this at the terminal:
/bin/bash -c 'echo hello world'
It prints hello world, right? How about this:
/bin/bash -c 'BASE=172.31.0.0; CMD=172.31.1.0; if [[ "$CMD" == "$BASE" ]]; then echo "ip are same"; else echo "not matched"; fi'
If any of the above doesn't work, you have a problem with your bash installation.
Instead of executing your script with ./script.sh, run it like this:
/bin/bash script.sh
Nothing? Run this:
file script.sh
If it ends with something like "with CRLF line terminators", then cdarke nailed it: the file was created on Windows with an improper tool. Recreate it on Linux or use dos2unix. But anyway, I doubt it because with a CRLF-ending file I get this printed:
bash: ./script.sh: /bin/bash^M: bad interpreter: No such file or directory
Instead of nothing at all.
Put those this line on the beginning of the file:
set -x
(below #!/bin/bash, if you have it). This ensures a debugging trace will be printed, showing each command as it is executed.
If still there is nothing shown.. put this at your script (below set -x if you put it):
touch /tmp/hi-this-is-strange
Then check if there is a /tmp/hi-this-is-strange file after you run the script.

Getting exit code of last shell command in another script

I am trying to beef up my notify script. The way the script works is that I put it behind a long running shell command and then all sorts of notifications get invoked after the long running script finished.
For example:
sleep 100; my_notify
It would be nice to get the exit code of the long running script. The problem is that calling my_notify creates a new process that does not have access to the $? variable.
Compare:
~ $: ls nonexisting_file; echo "exit code: $?"; echo "PPID: $PPID"
ls: nonexisting_file: No such file or directory
exit code: 1
PPID: 6203
vs.
~ $: ls nonexisting_file; my_notify
ls: nonexisting_file: No such file or directory
exit code: 0
PPID: 6205
The my_notify script has the following in it:
#!/bin/sh
echo "exit code: $?"
echo "PPID: $PPID"
I am looking for a way to get the exit code of the previous command without changing the structure of the command too much. I am aware of the fact that if I change it to work more like time, e.g. my_notify longrunning_command... my problem would be solved, but I actually like that I can tack it at the end of a command and I fear complications of this second solution.
Can this be done or is it fundamentally incompatible with the way that shells work?
My shell is Z shell (zsh), but I would like it to work with Bash as well.
You'd really need to use a shell function in order to accomplish that. For a simple script like that it should be pretty easy to have it working in both zsh and bash. Just place the following in a file:
my_notify() {
echo "exit code: $?"
echo "PPID: $PPID"
}
Then source that file from your shell startup files. Although since that would be run from within your interactive shell, you may want to use $$ rather than $PPID.
It is incompatible. $? only exists within the current shell; if you want it available in subprocesses then you must copy it to an environment variable.
The alternative is to write a shell function that uses it in some way instead.
One method to implement this could be to use EOF tag and a master script which will create your my_notify script.
#!/bin/bash
if [ -f my_notify ] ; then
rm -rf my_notify
fi
if [ -f my_temp ] ; then
rm -rf my_temp
fi
retval=`ls non_existent_file &> /dev/null ; echo $?`
ppid=$PPID
echo "retval=$retval"
echo "ppid=$ppid"
cat >> my_notify << 'EOF'
#!/bin/bash
echo "exit code: $retval"
echo " PPID =$ppid"
EOF
sh my_notify
You can refine this script for your purpose.

Resources