This question already has answers here:
Why do shell script comparisons often use x$VAR = xyes?
(7 answers)
Closed 4 years ago.
I'm trying to understand a script that will stop when executed as root:
#!/usr/bin/env bash
if [ x"$(whoami)" = x"root" ]; then
echo "Error: don't run this script as root"
exit 1
fi
I have tested this and it works as intended even if I remove the x in the if statement. My question is why is the x in x"$(whoami)" and x"root" needed?
basically the [ is a softlink to an external program called test, therefore the condition is passed to it as program arguments, and doing so if you don't surround a $variable with "$quotes" , and the variable happens to be empty it won't be considered as an empty argument, it will be considered as no argument (nothing)
#!/bin/bash -eu
var=bla
if [[ $var == bla ]];then
echo first test ok
fi
var=""
if [[ $var == "" ]];then
echo second test ok
fi
if [ "$var" == "" ];then
echo third test ok
fi
if [ x$var == "x" ];then
echo fourth test ok
fi
echo this will fail:
if [ $var == "" ];then
echo fifth test ok
fi
echo because it is the same as writing:
if [ == "" ];then
echo sixth test is obviously eroneous
fi
echo but also you should quote your variables because this will work:
var="a b"
if [ "$var" == "a b" ];then
echo seventh test ok
fi
echo ... but this one won\'t as test now has four arguments:
if [ $var == "a b" ];then
echo eighth test ok
fi
Related
This question already has answers here:
Getting "command not found" error while comparing two strings in Bash
(4 answers)
Closed 3 years ago.
I'm writing a bash script where i need to combine two conditions with && operator
var1=value
var2=1
if [-z $var1 ] && [$var2=="1"]; then
do something
else
do something else
fi
but it always executes the else part.
My research
google gave me bash conditions like this but its not working for me.
if [condition1] && [condition2]; then
do something
fi
Another method i tried is this but it still completely ignored the true part
if [[-z $var1 ]] && [$var2=="1"]; then
do something
else
do something else
fi
Tried with -a operator like this
if [-z $var1 -a $var2=="1" ]; then
tried nested if
if [-z $var1 ]; then
if [$var2=="1"]; then
do something
fi
else
do something else
fi
So i know i am doing something wrong but my goal is i want to check for any value in $var1 and also want $var2 condition to be true and execute the true part.
UPDATE
i tried this
#! /bin/bash
set -o nounset
#set -o errexit
set -o pipefail
set -o xtrace
var1=pop
var2=1
if test -z "$var1" && test "$var2" -eq 1; then
echo Y1
fi
if [ -z "$var1" ] && [ "$var2" -eq 1 ]; then
echo Y2
fi
and this is the output
root#c847b6423295:/# ./test.sh
+ var1=pop
+ var2=1
+ test -z pop
+ '[' -z pop ']'
root#c847b6423295:/#
What am i doing wrong ?
You want to encode "$var1 is not empty and $var2 is equal to 1", you can do:
if test -z "$var1" && test "$var2" -eq 1; then
echo Y
fi
which is equivalent to:
if [ -z "$var1" ] && [ "$var2" -eq 1 ]; then
echo Y
fi
If you want to compare strings, use a single equals sign:
if test "aaa" = "aaa"; then
echo Y
fi
I want to check, if multiple variable are set or not, if set then only execute the script code, otherwise exit.
something like:
if [ ! $DB=="" && $HOST=="" && $DATE=="" ]; then
echo "you did not set any variable"
exit 1;
else
echo "You are good to go"
fi
You can use -z to test whether a variable is unset or empty:
if [[ -z $DB || -z $HOST || -z $DATE ]]; then
echo 'one or more variables are undefined'
exit 1
fi
echo "You are good to go"
As you have used the bash tag, I've used an extended test [[, which means that I don't need to use quotes around my variables. I'm assuming that you need all three variables to be defined in order to continue. The exit in the if branch means that the else is superfluous.
The standard way to do it in any POSIX-compliant shell would be like this:
if [ -z "$DB" ] || [ -z "$HOST" ] || [ -z "$DATE" ]; then
echo 'one or more variables are undefined'
exit 1
fi
The important differences here are that each variable check goes inside a separate test and that double quotes are used around each parameter expansion.
If you are ok with writing a function for this purpose, it can be pretty convenient.
This solution uses the ${!VAR_NAME} syntax to check whether the variable is empty and has the added benefit of telling you which variable names are empty.
check_vars()
{
var_names=("$#")
for var_name in "${var_names[#]}"; do
[ -z "${!var_name}" ] && echo "$var_name is unset." && var_unset=true
done
[ -n "$var_unset" ] && exit 1
return 0
}
# Usage for this case
check_vars DB HOST DATE
echo "You are good to go"
I wound up using variable-variables to loop through an easily managed HEREDOC list of variable names:
# Ensure non-empty values.
# Loop through HEREDOC, test variable-variable isn't blank.
while read var; do
[ -z "${!var}" ] && { echo "$var is empty or not set. Exiting.."; exit 1; }
done << EOF
KUBE_NAMESPACE
DOCKER_REGISTRY
DOCKER_DEPLOY_USER
DOCKER_DEPLOY_PASSWORD
DOCKER_DEPLOY_EMAIL
EOF
You can check it also by put the variables name in a file
DB=myDB
HOST=myDB
DATE=myDATE
then test them if currently empty or unset
#!/bin/bash
while read -r line; do
var=`echo $line | cut -d '=' -f1`
test=$(echo $var)
if [ -z "$(test)" ]; then
echo 'one or more variables are undefined'
exit 1
fi
done <var.txt
echo "You are good to go"
Nice solution from #joe.still !
improvement is to exit after checking all variables
i=0
while read var; do
[ -z "${!var}" ] && { echo "$var is empty or not set. Exiting.."; let i=i+1; }
done << EOF
KUBE_NAMESPACE
DOCKER_REGISTRY
DOCKER_DEPLOY_USER
DOCKER_DEPLOY_PASSWORD
DOCKER_DEPLOY_EMAIL
EOF
if [ $i -gt 0 ]; then
echo $i
echo "exiting"
exit 1
fi
Good Day Everyone.
I've personally used this method in my bash scripts. Verified works on bash 4.4 and later in Ubuntu, openSUSE, and ClearLinux.
Can RHEL|CentOS|Alma and Arch Based users let me know it it works fine for you?
( [ "$VAR1""$VAR2""$VAR3""$VAR4""$VAR5" ] && echo -e " Warning: StackIsNotClear" ) || { echo -e " GoodNews: StackIsClear"; }
This question already has answers here:
Test for non-zero length string in Bash: [ -n "$var" ] or [ "$var" ]
(7 answers)
Closed 8 years ago.
I don't set any values for $pass_tc11; so it is returning null while echoing. How to compare it in if clause?
Here is my code. I don't want "Hi" to be printed...
-bash-3.00$ echo $pass_tc11
-bash-3.00$ if [ "pass_tc11" != "" ]; then
> echo "hi"
> fi
hi
-bash-3.00$
First of all, note you are not using the variable correctly:
if [ "pass_tc11" != "" ]; then
# ^
# missing $
Anyway, to check if a variable is empty or not you can use -z --> the string is empty:
if [ ! -z "$pass_tc11" ]; then
echo "hi, I am not empty"
fi
or -n --> the length is non-zero:
if [ -n "$pass_tc11" ]; then
echo "hi, I am not empty"
fi
From man test:
-z STRING
the length of STRING is zero
-n STRING
the length of STRING is nonzero
Samples:
$ [ ! -z "$var" ] && echo "yes"
$
$ var=""
$ [ ! -z "$var" ] && echo "yes"
$
$ var="a"
$ [ ! -z "$var" ] && echo "yes"
yes
$ var="a"
$ [ -n "$var" ] && echo "yes"
yes
fedorqui has a working solution but there is another way to do the same thing.
Chock if a variable is set
#!/bin/bash
amIEmpty='Hello'
# This will be true if the variable has a value
if [ $amIEmpty ]; then
echo 'No, I am not!';
fi
Or to verify that a variable is empty
#!/bin/bash
amIEmpty=''
# This will be true if the variable is empty
if [ ! $amIEmpty ]; then
echo 'Yes I am!';
fi
tldp.org has good documentation about if in bash:
http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html
Here is my code:
#!/bin/bash
echo "Letter:"
read a
if [ $a = "a" ]
then
echo "LOL"
fi
if [ $a = "b" ]
then
echo "ROFL"
fi
Is there a way for me to loop this so that, after displaying either LOL or ROFL, I would be asked for a letter again?
Yes.
Oh, you want to know how?
while true; do
echo "Letter:"
read a
if [ $a = "a" ]
then
echo "LOL"
elif [ $a = "b" ]
then
echo "ROFL"
fi
done
Of course, you probably want some way to get out of that infinite loop. The command to run in that case is break. I would write the whole thing like this:
while read -p Letter: a; do
case "$a" in
a) echo LOL;;
b) echo ROFL;;
q) break;;
esac
done
which lets you exit the loop either by entering 'q' or generating end-of-file (control-D).
Don't forget that you always want -r flag with read.
Also there is a quoting error on that line:
if [ $a = "a" ] # this will fail if a='*'
So here is a bit better version(I've also limited the user to input only 1 character):
#!/bin/bash
while true; do
read -rn1 -p 'Letter: ' a
echo
if [[ $a = 'a' ]]; then
echo "LOL"
elif [[ $a = 'b' ]]; then
echo "ROFL"
else
break
fi
done
Or with switch statement:
#!/bin/bash
while read -rn1 -p 'Letter: ' a; do
echo
case $a in
a) echo LOL;;
b) echo ROFL;;
*) break;;
esac
done
I'm receiveing an error on a simple script when using if/else statement.
The code:
#!/bin/sh
count=100
if [$count > 3]; then
echo "Test IF"
fi
The error: /bin/ash: line 6: [100: not found
#!/bin/sh
count=100;
if [ "$count" -gt 3 ]; then
echo "Test IF";
fi
Correct your syntax: spaces must be used around [ and ], parameter expansions must be quoted, and -gt is appropriate for numeric comparisons inside of [ ]. > in sh is used as redirection operator; if you want to use it in arithmetical comparison, you must use the bash-only syntax
$(( $count > 3 ))
#!/bin/sh
if [ $var -eq 12 ]; then
echo "This is a numeric comparison if example"
fi
if [ "$var" = "12" ]; then
echo "This is a string if comparison example"
fi
if [[ "$var" = *12* ]]; then
echo "This is a string regular expression if comparison example"
fi
The if statement in shell uses the command [.
Since [ is a command (you could also use 'test'), it requires a space before writing the condition to test.
To see the list of conditions, type:
man test
You'll see in the man page that:
s1 > s2 tests if string s1 is after string s2
n1 gt n2 tests if integer n1 is greater than n2
In your case, using > would work, because string 100 comes after string 3, but it is more logical to write
if [ $count -gt 3 ]; then
echo "test if"
fi
this will also do!
#!/bin/sh
count=100
if [ $count -gt 3 ];
then
echo "Test IF"
fi
if [[ "$x" == "true" ]]; then
echo "value matched"
else
echo "value doesn't matched"
fi