What is [[: not found error? - shell

I tried to execute a file containing a shell script.
I get an error called "[[: not found" error at the last line. How to resolve it?

[[ is bash. sh wants the [ variant.
Either change that to /usr/bin/bash (or wherever bash is located on your system), or adjust the expression accordingly:
if [ status_of_job -eq 0 ];

[ is actually an executable in linux. but [[ is not.
Try
if [ status_of_job -eq 0 ]; then
(note the single [] set).

This interpreter:
#!/usr/bin/sh
Is either not bash or your file doesn't have the shebang in the right place.
ls -l /usr/bin/sh will tell you if it's a symlink to something other than bash.
If it is bash, then check that there's no leading characters before the #!.

You may find you stumble at other blocks later with POSIX shell related issues. People don't really understand how much bash actually provides until it's taken away. Take a look at this so you can hopefully avoid any other issues:
http://pubs.opengroup.org/onlinepubs/7908799/xcu/shellix.html

Related

How to check whether utility 'realpath' is available for the script?

We were asked to write a project in shell that should be compatible with every general shell (dash, ksh, bash). We should also cover the possible option that the utility realpath is not available on a particular machine. Is there any easy way how to checks if the utility is present or not?
Checking if an executable is available can be done in several ways. One simple way is to just run it, and check the return code. If you don't want to see the error, redirect it:
realpath yourArgument 2> /dev/null
echo $?
Or in a if:
realpath yourArgument 2> /dev/null
if [ $? -eq 127 ]; then
#Realpath is missing!
fi
This way if realpath worked and is in the path you will have the real path printed, otherwise you enter the if. Note 0 is the agreed upon success status, adn 127 is the error code indicating missing command (Thanks #user1934428, I used previously -gt 0 which may fail since realpath may return non-0 status.)
If I did not understand bad, you want to know whether a certain utility exists to check if a directory exists?. If so, I have used this line always in several shells and I have not found problems.
if [ -d "$DIRECTORY" ]; then
# Control will enter here if $DIRECTORY exists.
fi

Why is executing a ruby command on bash to command file not working?

Code from .command file:
cd "$(dirname "$0")"
g1=Hi-Lo
echo Welcome to Ruby_Games! So far, you can play $g1.
echo What game would you like to play?
read game_choice
if [$game_choice == $g1]
then
ruby Hi-Lo.rb
fi
Output:
Welcome to Ruby_Games! So far, you can play Hi-Lo.
What game would you like to play?
Hi-Lo
/Users/Abbas/Desktop/Ruby_Games/LAUNCHER.command: line 6: [Hi-Lo: command not found
logout
So what exactly is going wrong? Thanks
I believe you need double quotes in your if statement
Similar to example 6.4 here: http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-6.html
cd "$(dirname "$0")"
g1=Hi-Lo
echo Welcome to Ruby_Games! So far, you can play $g1.
echo What game would you like to play?
read game_choice
if [ "$game_choice" = "$g1" ]
then
ruby Hi-Lo.rb
fi
You need spaces between each element of the test (aka [) command. That is, you need a space between [ and $game_choice, between $game_choice and =, etc. Also, as #GregHNZ pointed out, you should use double-quotes around variable references, in case they contain spaces or certain other shell metacharacters. Finally, == in a test expression is a bash extension; use = instead, and it'll work in more basic shells as well. Result:
if [ "$game_choice" = "$g1" ]
Spaces are important delimiters in shell syntax; there are places they're required and places they're forbidden, and very very few places where they're optional. In many languages, you can add or remove spaces to make the code more readable, but that's not the case in shell.
BTW, I recommend using shellcheck.net; it does a pretty good job of spotting errors like this. Actually, it points out a couple I didn't think of: you should add a shebang line to the beginning of the script, and using cd without checking for an error risks the rest of the script running in an unexpected directory. So you should use something like this:
#!/bin/bash
cd "$(dirname "$0")" || {
echo "Error cd'ing to the script's directory" >&2
exit 1
}

Bash script giving me a different result on reboot?

I worked on a Bash script for the last day or so and running and debugging it directly on the shell.
The final script will be executed when the Ubuntu server gets rebooted.
I have started testing this, but my script gives me a different result then what I was expected.
I have narrowed it down to an "or condition" and rewrote a more simpler script to test this anomaly:
A call to this script has been made in /etc/rc.local, with a redirection of the output to a log file (log/reboot.log).
I have this in my script (as a test):
#!/bin/bash
YESTERDAY=20131103
SYS_DATE=20131104
LAST_START=20131104
if [[ $LAST_START = $YESTERDAY || $LAST_START = $SYS_DATE ]];
then
echo "is equal"
else
echo "is not equal"
fi
Executing in the shell I get "is equal" (the right answer). After the reboot in the log I get "is not equal".
Could someone tell me why?
I am guessing here,
But do you realize your /bin/sh is not your SHELL.
In UBUNTU and Debian, /bin/sh is DASH, your login shell is BASH.
So it might be related to your syntax of [[ ]] which is BASH.
Did you right in your top of the script:
#!/bin/sh
or
#!/bin/bash
[[
The [[ builtin is a bashism, and has somewhat better-defined semantics
than [ (a.k.a. test). However, it is still quite reasonable to use [
instead, and portable scripts must do so. Note that argument handling
is not quite the same; as above, use = rather than ==.
See here:
https://wiki.ubuntu.com/DashAsBinSh
the right way to do stuff here
The best solution would be actually to put your script in /etc/init.d and link it to run level 6. Which is the run level executed when rebooting. You should consider reading man 8 init when you have got some spare time. It will help you understand how your system is starting and shuting down.

while loop in while loop in bash script isn't properly highlighted in vim

I am trying to write a while loop within one while loop in bash , the syntax of the second while doesn't get highlighted . Is there any special syntax for using this ?
while [ "ka" = $name ]
do
while [ "ka" = $name ] //this while is not highlighted
do
done
done
As other answers have already pointed out, this is a bug in the syntax plugin that affects non-Bash shell syntax.
Please submit a bug report (basically a link to this page) to the script's author, Charles Campbell; his email address is in the script's header; the script is located at syntax/sh.vim in the Vim install directory.
Should you not get a response, please inform the vim_dev mailing list (cp. http://www.vim.org/community.php; you need to register first) about this; hopefully, someone else will pick it up.
workaround
As a workaround, you could force Bash syntax by default (in your ~/.vimrc):
:let g:is_bash = 1
You're right. For some reason it looks like VIm 7.3 only highlights nested while commands if the shebang line points to bash. For example, files starting with any of these are highlighted correctly:
#!/usr/bin/env bash
#!/usr/bin/bash
#!/bin/bash
But not without a shebang line or with the following lines:
#!/bin/sh
#!/usr/bin/env sh
Test file:
[shebang line]
while true
do
while true
do
while true
do
:
done
done
done
:set filetype? prints filetype=sh in all cases, so it looks like it's a bug.
Try the following script. It works for me
#!/bin/bash
i="1"
while [ $i -lt 4 ]
do
j="1"
while [ $j -lt 4 ]
do
echo $i
j=$[$j+1]
done
i=$[$i+1]
done
It's output is
1
1
1
2
2
2
3
3
3
As expected.
The problem might be the code prior to the one you posted here, since I can't really find a syntax error in your code.

BASH: if statement execute command and function

I've run into an issue in which I think should be easy to resolve, but for the life of me, I can't figure it out. Could be that it's really late; not sure.
So I have a shell script and I have an if statement that I need to run. The problem is that I have a function inside this bash script that I am using to actually build part of this find command inside the if statement. I want to know how I can do both, without receiving an error [: too many arguments.
Here's the current code:
if [ -n `find ./ `build_ext_names`` ];then
That's all I really need to post. I need to figure out how to run that build_ext_names inside that find command, which in-turn is inside the ifstatement
Michael Aaron Safyan has the right idea, but to fix the immediate problem you can just use the simpler $(command) construct instead of ```command` `` for command substitution. It allows for much simpler nesting:
if [ -n "$(find ./ "$(build_ext_names)")" ]; then
This is easier if you split it up:
function whateverItIsYouAreTryingToDo() {
local ext_names=$(build_ext_names)
local find_result=$(find ./ $ext_names)
if [ -n "$find_result" ] ; then
# Contents of if...
fi
}

Resources