LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Bash script not performing a check properly (https://www.linuxquestions.org/questions/programming-9/bash-script-not-performing-a-check-properly-4175420678/)

da_667 08-06-2012 12:40 PM

Bash script not performing a check properly
 
Hello,

I'm trying to throw together a bash script on Ubuntu Server 12.04. One of the sub-portions of the script is verifying wget exists in /usr/bin. If it doesn't exist, my script offers to install it via apt-get.

Here's a potion of my script that is giving me problems. For ease of debugging, I made it its own shell script:

Code:

#!/bin/sh
echo "Finding wget..."
        if [ $(ls -al /usr/bin/ | grep wget | cut -f16 -d " ") != "wget" ]
                then
                        echo "wget not found. Install wget?"
                        read wget_install
                                if $wget_install = ["yes"] || ["y"]
                                        then
                                                echo "installing wget. \n"
                                                apt-get install -y wget
                                        else
                                        echo "Either you have selected no, or I didn't understand what you entered. wget is required to continue. after the installer is finished, you may remove wget at your discretion."
                                fi
                else
                        echo "found wget."
        fi
exit 0

when this script is ran, I get

Code:

root@Gatekeeper:~# sh wgetcheck.sh
Finding wget...
wgetcheck.sh: 3: [: !=: unexpected operator
found wget.

So the unexpected operator error leads me to believe it's not doing the logic check I want it to do. I've used the same programming logic to do other system checks (e.g. network connectivity, which user are we running as, etc.) and there's no problem, so I'm a little stumped. Thanks in advance for any assistance you provide.

Kustom42 08-06-2012 12:56 PM

Try switching it to :

Code:

if [ -z $(ls -al /usr/bin/ | grep wget | cut -f16 -d " ") ]
You could also do it this way:

Code:

/usr/bin/which wget

if [ $? -ne 0 ]
then
                        echo "wget not found. Install wget?"
                        read wget_install
                                if $wget_install = ["yes"] || ["y"]
                                        then
                                                echo "installing wget. \n"
                                                apt-get install -y wget
                                        else
                                        echo "Either you have selected no, or I didn't understand what you entered. wget is required to continue. after the installer is finished, you may remove wget at your discretion."
                                fi
                else
                        echo "found wget."
        fi

Using exit codes is more reliable than doing a cut statement.

whizje 08-06-2012 12:58 PM

It is bad practice relying on ls better use if file exist
Code:

if [ -e "/usr/bin/wget" ]; then echo "hurrah"; fi

Kustom42 08-06-2012 01:01 PM

Quote:

Originally Posted by whizje (Post 4747390)
It is bad practice relying on ls better use if file exist
Code:

if [ -e "/usr/bin/wget" ]; then echo "hurrah"; fi

I also agree with this solution, using exit codes or a hard test statement such as this against the file is the best coding practice, using cut, grep etc.. causes some inconsistent results.

da_667 08-06-2012 01:35 PM

I've tried utilizing both methods (the -z and utilizing exit code checks) and they both work, now I run into a problem where the read statement works, but the portion where the script is looking for y or yes to indicate yes is not working. For readability, let me post version 2:

Code:


#!/bin/sh
/usr/bin/which wget
if [ $? -ne 0 ]
then
        echo "wget not found. Install wget?"
        read  wget_install
                if $wget_install = ["yes"] || ["y"]
                        then
                                echo "installing wget. \n"
                                apt-get install -y wget
                        else
                        echo "Either you selected no or I didn't understand. Wget is required to continue."
                        exit 1
                fi
        else
                echo "found wget."
fi

exit 0

Identical to Kustom42's version with exit codes for verification. Now when I run the script, the y || yes isn't being parsed correctly. Either that or I'm borking this pretty badly again. Here are outputs I get:

if the word yes is entered:

I get an infinite loop where the text "= [yes]" is returned repeatedly.

if I enter y, I get this:

Code:

root@Gatekeeper:~# sh wgetcheckv2.sh
wget not found. Install wget?
y
wgetcheckv2.sh: 7: wgetcheckv2.sh: y: not found
wgetcheckv2.sh: 7: wgetcheckv2.sh: [y]: not found
Either you selected no or I didn't understand. Wget is required to continue.
root@Gatekeeper:~#

if I enter any other input, I get this:

Code:

root@Gatekeeper:~# sh wgetcheckv2.sh
wget not found. Install wget?
n
wgetcheckv2.sh: 7: wgetcheckv2.sh: n: not found
wgetcheckv2.sh: 7: wgetcheckv2.sh: [y]: not found
Either you selected no or I didn't understand. Wget is required to continue.
root@Gatekeeper:~#

Thoughts? thanks for the help thus far.

suicidaleggroll 08-06-2012 01:46 PM

You can't do tests that way.

Break it out of the script and just run it from the command line. Does this work?
Code:

if y = ["yes"] || ["y"]; then echo 1; fi
?

If not, modify it until it does, then put the corrected version back into the script. The nice thing about scripting languages is you don't need the entire code to test one line. You can test that if statement by itself from the command line until it works, then insert the working version into the script.

Roken 08-06-2012 01:58 PM

Alternatively, use case:

Code:

#!/bin/sh
/usr/bin/which wget
if [ $? -ne 0 ]; then
        echo "wget not found. Install wget?"
        read  wget_install
        case $wget_install in
        [yY] | [yY][Ee][Ss])
                echo "installing wget. \n"
                apt-get install -y wget
                ;;
        *)
                echo "Either you selected no or I didn't understand. Wget is required to continue"
                exit 1
                ;;
        esac
else
        echo "found wget."
fi
exit 0


da_667 08-06-2012 02:24 PM

Quote:

Originally Posted by Roken (Post 4747436)
Alternatively, use case:

Code:

#!/bin/sh
/usr/bin/which wget
if [ $? -ne 0 ]; then
        echo "wget not found. Install wget?"
        read  wget_install
        case $wget_install in
        [yY] | [yY][Ee][Ss])
                echo "installing wget. \n"
                apt-get install -y wget
                ;;
        *)
                echo "Either you selected no or I didn't understand. Wget is required to continue"
                exit 1
                ;;
        esac
else
        echo "found wget."
fi
exit 0


You know,

I didn't even think to use a case statement. thank you very much for this. I ended up getting the or statement to evaluate, then I ran into a snag where the script would not take no for an answer. This solves the problem very well.

Thanks again!

Kustom42 08-06-2012 02:29 PM

Just an informational follow up, this could have been done pretty easily with the "select" function as well:

http://tldp.org/LDP/Bash-Beginners-G...ect_09_06.html

da_667 08-06-2012 02:34 PM

Quote:

Originally Posted by Kustom42 (Post 4747457)
Just an informational follow up, this could have been done pretty easily with the "select" function as well:

http://tldp.org/LDP/Bash-Beginners-G...ect_09_06.html

Duly noted...

thanks again!

suicidaleggroll 08-06-2012 02:40 PM

FYI - a working if could have looked like:
Code:

if [[ "$wget_install" == "y" || "$wget_install" == "yes" ]]

Kustom42 08-06-2012 02:50 PM

Quote:

Originally Posted by suicidaleggroll (Post 4747462)
FYI - a working if could have looked like:
Code:

if [[ "$wget_install" == "y" || "$wget_install" == "yes" ]]

I have read that the format here works but I have never been able to get it to work, as an altnerate I always use:

Code:


if [ "$wget_install" -eq "y" ] || [ "$wget_install" -eq "yes" ]

Not to hijack the thread but can anyone shed some light on why this occurs? I believe it is related to the "[[" double brackets and its probably me only using single brackets but want to confirm.

suicidaleggroll 08-06-2012 03:02 PM

Quote:

Originally Posted by Kustom42 (Post 4747470)
I have read that the format here works but I have never been able to get it to work, as an altnerate I always use:

Code:


if [ "$wget_install" -eq "y" ] || [ "$wget_install" -eq "yes" ]

Not to hijack the thread but can anyone shed some light on why this occurs? I believe it is related to the "[[" double brackets and its probably me only using single brackets but want to confirm.


-eq is used for integer comparison, == is used for string comparison. This page gives a nice rundown of the differences between "[" and "[[".

http://mywiki.wooledge.org/BashFAQ/031

Essentially it boils down to "[" is older and more compatible, "[[" is newer and more powerful.

Kustom42 08-06-2012 03:07 PM

Thanks for the clarification suicidaleggroll.

whizje 08-06-2012 03:08 PM

nevermind
http://tldp.org/LDP/abs/html/testcon...ml#DBLBRACKETS
The [[ ]] construct is the more versatile Bash version of [ ]. This is the extended test command, adopted from ksh88.
Using the [[ ... ]] test construct, rather than [ ... ] can prevent many logic errors in scripts. For example, the &&, ||, <, and > operators work within a [[ ]] test, despite giving an error within a [ ] construct.
Arithmetic evaluation of octal / hexadecimal constants takes place automatically within a [[ ... ]] construct.

Roken 08-06-2012 03:16 PM

It's the beauty of bash. There are many ways to skin a cat, but you still finish up with a skinned cat. :)


All times are GMT -5. The time now is 04:20 AM.