bash string not matching in if clause - bash

I am running into a strange issue. In the below piece of code the echo statement works fine and in success.txt I get b4 running=false with RUNNING:false which means $RUNNING = false.
But it is not going into the if block.
echo "b4 running=false with RUNNING:"$RUNNING >> /tmp/success.txt
if [[ $RUNNING == "false" ]]; then
echo "in running=false" >> /tmp/success.txt
exit 2
fi
I also tried
if [[ $RUNNING == false ]]; then
echo "in running=false" >> /tmp/success.txt
exit 2
fi
if [ "$RUNNING" == "false" ]; then
echo "in running=false" >> /tmp/success.txt
exit 2
fi
if [ "$RUNNING" == false]; then
echo "in running=false" >> /tmp/success.txt
exit 2
fi
if [ "$RUNNING" == "false" ]; then
echo "in running=false" >> /tmp/success.txt
exit 2
fi
None of these is working. I am sure I am missing something very small here.

When I try
RUNNING=false
if [[ $RUNNING == false ]]; then
echo 1
fi
if [ "$RUNNING" == "false" ]; then
echo 2
fi
if [ "$RUNNING" == false]; then
echo 3
fi
if [ "$RUNNING" == "false" ]; then
echo 4
fi
I get
1
2
/tmp/a.sh: line 10: [: missing `]'
4
Fixing the third one from
if [ "$RUNNING" == false]; then
to
if [ "$RUNNING" == false ]; then
Note the additional space between false and ].
Now I get
1
2
3
4
So all four are valid, if $RUNNING is false. The difference might be a trailing new line character or some white space around false/$RUNNING, if the value is captured from the output of some command.
See Conditional Constructs and Bash Conditional Expressions for more details.

have you tried the following:
if [ $RUNNING == "false" ]; then
echo "test"
fi
That seems to work for me.
Cheers

Related

Bash Command Nested conditional statements failing, but why

I have a bash script that runs many conditional statements, but when I run the script, it only hits the following line: if [ $? -eq 0 ]
touch /tmp/converted.json
tool test --json --all-projects | tee >> /tmp/converted.json
ret=$?
set -o pipefail
#no vulns
if ((ret == 0)); then
echo "Hooray!"
#found vulns
elif ((ret == 1)); then
then
#check single project
if [[ $firstchar == "{" ]]
then
echo "SINGLE PROJECT"
elif [[ $firstchar == "[" ]]
then
echo "MULTIPROJECT"
else
echo "didnt get a single or multiproject"
fi
#error with your command
elif ((ret == 2)); then
then
echo "An error occurred"
#no manifest
elif ((ret == 3)); then
then
echo "Ensure your repo has a proper required manifest file"
else
echo "Something else occurred"
fi
Thus, why does this continue to hit if((ret==0)) condition?
Thanks
$? has the exit status of the last command executed. The last command at elif [ $? -eq 1 ] was [ executed at if [ $? -eq 0 ].
if [ $? -eq 0 ] # executes `[`
then
: dont care
elif [ $? -eq 1 ] # $? here has a nonzero the exit status of `[`
Just save the exit status to a variable before calling any command right after executing the command you are interested in. In bash you may use arithmetic expansion ((...)).
some_command
ret=$?
if ((ret == 0)); then
: dont care
elif ((ret == 1)); then

Complicated if-then-else statement

So, I simplified this code. Every time it runs, else or $msg4 is always executed. How do I change it so it only does else if the $nick part doesn't match?
if [ "$who" = "$nick1" ]
then echo $msg1
fi
if [ "$who" = "$nick2" ]
then echo $msg2
fi
if [ "$who" = "$nick3" ]
then echo $msg3
else $msg4
fi
Here you can read how Bash if statements work: https://www.gnu.org/software/bash/manual/html_node/Conditional-Constructs.html#Conditional-Constructs
There you can see there is an elif which you should use to chain multiple if - else things together so that the final else is only executed if none of the if statements match. Result:
if [ "$who" = "$nick1" ]
then
echo $msg1
elif [ "$who" = "$nick2" ]
then
echo $msg2
elif [ "$who" = "$nick3" ]
then
echo $msg3
else
echo $msg4
fi
You can also write the then on the same line as if if you add a ; before then:
if [ "$who" = "$nick1" ]; then
echo $msg1
elif [ "$who" = "$nick2" ]; then
echo $msg2
elif [ "$who" = "$nick3" ]; then
echo $msg3
else
echo $msg4
fi
This is often easier to read.
Use case .. esac
case "$who" in
"$nick1") echo "$msg1";;
"$nick2") echo "$msg2";;
"$nick3") echo "$msg3";;
*) echo "$msg4";;
esac

How to call another script within a script with bash

Hello here is my primary script. The test2.sh is just an echo "it worked"
what happens when I try and call from the original loop, it gets to the correct file then echo's infinite "it worked" where it should just be doing it once.
Any idea why? I really want to have another loop called outside of the main script that won't interfere, but still learning bash =P
#!/bin/bash
number=1
while true
do
if [ "$number" -eq "1" ]; then
echo "hello 1!"
elif [ "$number" -eq "2" ]; then
echo "hello 2!"
elif [ "$number" -eq "3" ]; then
echo "hello 3!"
elif [ "$number" -eq "4" ]; then
./test2.sh & continue
fi
sleep 5
((number++))
echo $number
done
first observation & is not a logical operator, & runs the precedding command in the background. Use && for logical operations.
what you need is a break keyword not a continue keyword . If you use the break keyword, the loop will stop executing. The continue keyword only rexecutes the loop , and since number is 4 , this branch of code will always run elif [ "$number" -eq "4" ]; then
working code
#!/bin/bash
number=1
while true
do
if [ "$number" -eq "1" ]; then
echo "hello 1!"
elif [ "$number" -eq "2" ]; then
echo "hello 2!"
elif [ "$number" -eq "3" ]; then
echo "hello 3!"
elif [ "$number" -eq "4" ]; then
./test2.sh && break
fi
sleep 5
((number++))
echo $number
done
or you can do this
for number in {1..4};do
(( number == 4 )) && ./test2.sh || echo "$number"
sleep 5
done

How can I perform an if/else using the shorthand form within a Bash string?

Without having to type out another block of if/else statements, how can I accomplish this within the string?
I want to avoid having to set the wording based on the boolean. The output from the script takes in cronjob_status as a boolean, which in turns does things based on the true/false value. I need to perserve the boolean that's being passed in via stdin for cronjob_status and I want to print the correct word.
if [ "${cronjob_status}" == True ]; then
cronjob_status_display = "enable"
else
cronjob_status_display = "disable"
fi
if [ $? -eq 0 ]
then
echo "Successfully ${cronjob_status_display} the cronjob"
else
echo "Could not create cronjob" >&2
fi
Add a short circuit evaluation, &&:
if [ $? -eq 0 ] && [ "${cronjob_status}" == True ]; then
echo "OK"
else
echo "NOT OK" >&2
fi
If you use the bash builtin [[, then this can also be written as :
if [[ $? -eq 0 && ${cronjob_status} == True ]]; then
echo "OK"
else
echo "NOT OK" >&2
fi
As a side note, you don't necessarily need to check the exit status with $?, you can run the command and check at once after that, for example if the command is e.g. /foo/bar, you could do:
if /foo/bar &>/dev/null && [[ ${cronjob_status} == True ]]; then
echo "OK"
else
echo "NOT OK" >&2
fi
You can use:
[[ $cronjob_status == True ]] &&
cronjob_status_display=enable || cronjob_status_display=disable
A one liner:
[[ $? -eq 0 ]] && echo "Successfully ${cronjob_status} the cronjob" || echo "Could not create cronjob" >&2

bash : Illegal number

When I run this bash script :
if [ [$EUID -ne 0] ]; then
echo "This script must be run as root" 1>&2
exit 1
else
printf " whathever "
exit 0
fi
I have this error :
./myScript: 15: [: Illegal number: [
Do you see any problem ?
You have syntax error in your if condition, use this if condition:
if [ "$EUID" -ne 0 ];
OR using [[ and ]]
if [[ "$EUID" -ne 0 ]];
You have syntax error in your if condition, use this if condition:
if [ "$EUID" -ne 0 ];
OR using [[ and ]]
if [[ "$EUID" -ne 0 ]];
If you use the KSH88+/Bash 3+ internal instruction [[, it's not necessary to use doubles quotes around the variables operands :
[ ~/test]$ [[ $var2 = "string with spaces" ]] && echo "OK" || echo "KO"
OK
Instead of the external command test or his fork [ :
[ ~/test]$ [ $var2 = "string with spaces" ] && echo "OK" || echo "KO"
bash: [: too many arguments
KO
[ ~/test]$ [ "$var2" = "string with spaces" ] && echo "OK" || echo "KO"
OK
Of course, you also have to choose the operators according to the type of operands :
[ ~/test]$ var1="01"
[ ~/test]$ [ "$var1" = "1" ] && echo "OK" || echo "KO"
KO
[ ~/test]$ [ "$var1" -eq "1" ] && echo "OK" || echo "KO"
OK
two suggestions apart from what everyone else has pointed out already.
rather than doing else [bunch of code because we are root] fi, just replace the else with fi. once you've tested for the failure condition you are concerned about and taken appropriate action, no need to continue to be within the body of the conditional.
$EUID is a bashism, if you would like to make this portable to shells such as ksh, replacing it with:
if [ $(id -u) -ne 0 ]; then echo "ur not root bro"; exit 1; fi
would be a good way to do it.
using
sudo bash shell_script.sh
instead of
sudo sh shell_script.sh
solved in my case.

Resources