i am getting [: argument excepted in unix command - shell

I have a code similar to below:
while [ $k = 0 ];
do
if [ $Year1 = $Year2 ] && [ $Month1 = $Month2 ]; then
echo "abcd"
else
echo"erty"
The error is line highlighted line > line 144]: [: argument expected

At least one of your variables contains unexpected data (e.g. is empty, or has spaces or new line characters), causing the [ command to not receive the arguments it expects.
Always quote your variables ("$Year1" instead of $Year1) to avoid surprises like this one.

while [ "$k" = 0 ]; do if [[ $Year1 == $Year2 && $Month1 == $Month2 ]]; then echo "abcd"; else echo "erty"; fi; done
Helpfull could be: https://www.shellcheck.net

You should use == for comparisons instead of = and also please use -eq whenever you want to use == if your code is for integer comparison. For example,
if [ $FLAG -eq 1 ];then
For strings, you can use =, like for example NOTE : Edited as pointed by Sir Athos
if [ "$Year1" = "$Year2" ] && [ "$Month1" = "$Month2" ]; then
or if you are comparing variable with string then, you can also use ==,
if [ "$STA" == "Completed" ];then
Adding test script to further clarify :
-bash-4.2$ cat string.sh
#!/bin/bash -x
str1="Hello There"
str2="Hello There"
if [ "$str1" = "$str2" ];then
echo "Matched"
else
echo "Not Matched"
fi
if [ "$str1" == "Hello There" ];then
echo "Matched"
else
echo "Not Matched"
fi
-bash-4.2$ ./string.sh
+ str1='Hello There'
+ str2='Hello There'
+ '[' 'Hello There' = 'Hello There' ']'
+ echo Matched
Matched
+ '[' 'Hello There' == 'Hello There' ']'
+ echo Matched
Matched
-bash-4.2$

Related

If statement returning error in shell script? [duplicate]

I would like to write in one line this:
if [$SERVICESTATEID$ -eq 2]; then echo "CRITICAL"; else echo "OK"; fi
So to do a test in my shell I did:
if [2 -eq 3]; then echo "CRITICAL"; else echo "OK"; fi
The result is
-bash: [2: command not found
OK
So it doesn't work.
Space -- the final frontier. This works:
if [ $SERVICESTATEID -eq 2 ]; then echo "CRITICAL"; else echo "OK"; fi
Note spaces after [ and before ] -- [ is a command name! And I removed an extra $ at the end of $SERVICESTATEID.
An alternative is to spell out test. Then you don't need the final ], which is what I prefer:
if test $SERVICESTATEID -eq 2; then echo "CRITICAL"; else echo "OK"; fi
Write like this, space is required before and after [ and ] in shell
if [ 2 -eq 3 ]; then echo "CRITICAL"; else echo "OK"; fi
Shorter format.
( [ 2 -eq 3 ] && echo "CRITICAL" ) || echo "OK"
Regex pattern type numbers : 10,12.1,+3.33,-1,0004,-48.9
Oneliner attacks again!
( [ `echo $number 2>/dev/null | grep -E "^[ ]*(\+|\-){0,1}[0-9]+(\.[0-9]+)?$"` ] && echo "NUMBER" ) || echo "NOT NUMBER"

How to use elif with && and -o in a bash script properly

Bash version 4.4.20
Ubuntu 16.04
I need to compare time and extensions for a particular project I have. Below is something similar to what I am trying to do but the error is the same. I am not sure where exactly the error is as shellcheck is not producing one.
#!/bin/bash
#
while read -r filename; do
extension="${filename##*.}"
if [ "$extension" == "zip" ] && [ "$filename" == "one.zip" ]; then
echo "Filename is $filename"
elif [ "$extension" == "zip" ] && [ "$filename" == "file_1.zip" ] -o [ "$filename" == "file_2.zip" ] -o [ "$filename" == "file_3.zip" ]; then
echo "Filename is $filename"
elif [ "$extension" == "csv" ] && [ "$filename" == "two.csv" ]; then
echo "Filename is $filename"
else
echo "Filename is $filename"
fi
done<fileList.txt
Error:
Filename is one.zip
check.sh: line 8: [: too many arguments
Filename is file_1.zip
check.sh: line 8: [: too many arguments
Filename is file_2.zip
check.sh: line 8: [: too many arguments
Filename is file_3.zip
Filename is two.csv
Filename is three.sql
Use pattern matching to your advantage:
while IFS= read -r filename; do
if [[ "$filename" = one.zip ]; then
echo "Filename is $filename"
elif [[ "$filename" = file_[123].zip ]; then
echo "Filename is $filename"
elif [[ "$filename" = two.csv ]; then
echo "Filename is $filename"
else
echo "Filename is $filename"
fi
done < fileList.txt
A case statement will work in any POSIX shell, not just a shell that supports a bash-like [[ ... ]] command.
while IFS= read -r filename; do
case $filename in
one.zip) echo "Filename is $filename" ;;
file_[123].zip) echo "..." ;;
two.csv) echo "..." ;;
*) echo "..." ;;
esac
done
To match a range of years(?), you can use
case $value in
200[0-9]|201[0-9]|202[0-1]) echo "Year between 2000 and 2021" ;;
esac
You can't do that as simply with [[ value = ... ]], since the | is part of the case statement's syntax, not an alternation operator in the pattern. Instead, you would need multiple match operators:
if [[ $value = 200[0-9] || $value = 201[0-19] || $value = 202[0-1] ]]; then
Here an explanation for why you get this error, as you get already good answers on how to do it correctly:
Note that the command [ is equivalent to test, hence your line 8 in effect (also removing unnecessary quotes) contains:
elif test "$extension" == zip ] && test "$filename" == file_1.zip ] -o [ "$filename" == file_2.zip ] -o [ "$filename" == file_3.zip ]
From the test man-page, we can see that the closing ] is optional, but if it is present, it terminates the expression to be tested.
The first test, which is just
test "$extension" == "zip" ]
is fine in this respect, but the second one starts with
test "$filename" == file_1.zip ] -o [ ...
Hence, when parsing the arguments, test encounters a ] and knows that this is the terminator for the arguments, but then finds another argument (-o), and doesn't know what to do with it. Hence it complains that it has got too many arguments
I have updated the syntax to what I think is the modern bash idioms. The script now works. Please correct me if I missed something else :
#!/bin/bash
#
while read -r filename
do
extension="${filename##*.}"
if [[ "$extension" = "zip" && "$filename" = "one.zip" ]]
then
echo "Filename is $filename"
elif [[ "$extension" = "zip" && "$filename" = "file_1.zip" ]] \
|| [[ "$filename" = "file_2.zip" ]] \
|| [[ "$filename" = "file_3.zip" ]]
then
echo "Filename is $filename"
elif [[ "$extension" = "csv" && "$filename" = "two.csv" ]]
then
echo "Filename is $filename"
else
echo "Filename is $filename"
fi
done < fileList.txt
Regards!

[: : integer expression expected

COUNTER=0
let COUNTER=COUNTER+1
count=`ssh -i /var/www/.ssh/id_rsa_root -o stricthostkeychecking=no $host $cmd`
count1=`echo $count | awk '{print $4}'`
printf "count1 : $count1\n"
result1=${count1/.*}
if [ "$result1" -ge "0" ]; then
echo $host
else
echo $host
exit
fi
If the value of $result1 is INTEGER and greater than zero, it'll goto IF loop (works fine for me)
But when it is not INTEGER, it is coming to else loop (which it is suppose to do) with the following error in the Output
line 55: [: : integer expression expected
but i dont want the above error in my output. I tried to use 2>/dev/null with this but no luck.
please help!
If you want to handle an empty result gracefully, check for it explicitly:
if [ -z "$result1" ]; then
: "ignoring empty string"
elif [ "$result1" -ge 0 ]; then
printf '%s\n' "$host"
else
printf '%s\n' "$host"
exit
fi
You could also check if result1 is a valid integer before making arithmetic comparisons:
function isNumber () {
[[ $1 =~ ^-?[0-9]+$ ]]
}
if ! isNumber "$result1"; then
echo "not a number"
elif [ "$result1" -ge "0" ]; then
echo "null or positive"
else
echo "negative"
fi
Change if [ "$result1" -ge "0" ]; then to
if (( result1 >= 0 )); then
This syntax won't throw any errors if result1 isn't defined (or empty) or happen to be a string somehow.

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.

Regarding Bash substring comparison

I try to test if a string starts with a certain prefix. But my script seems not work (I would expect the "if" branch will not get run). Can some Bash expert help to take a look? thanks!
Here is my code and test result:
$ cat testb.bash
#!/bin/bash
my_var="abcdefg";
if [[ "${my_var:0:5}"=="order" ]]; then
echo "value of my_var is ${my_var}.";
fi;
if [[ "${my_var:0:5}" -eq "order" ]]; then
echo "value of my_var is ${my_var}.";
fi;
if [ "${my_var:0:5}"="order" ]; then
echo "value of my_var is ${my_var}.";
fi;
$ bash -x testb.bash
+ my_var=abcdefg
+ [[ -n abcde==order ]]
+ echo 'value of my_var is abcdefg.'
value of my_var is abcdefg.
+ [[ abcde -eq order ]]
+ echo 'value of my_var is abcdefg.'
value of my_var is abcdefg.
+ '[' abcde=order ']'
+ echo 'value of my_var is abcdefg.'
value of my_var is abcdefg.
$
Whitespace is significant in this case. As you can see in the -x output, it understands the first condition as
[[ -n "${my_var:0:5}==order" ]]
Moreover, to test for a prefix, you can use a pattern:
[[ $my_var == order* ]]
To test the existence of substring, you can use either of these:
if [[ "$j" =~ string1 ]]; then
if [[ $j == *string1* ]]; then
In your particular case, you miss a space surounding ==, so instead of
if [[ "${my_var:0:5}"=="order" ]]; then
it should be
if [[ "${my_var:0:5}" == "order" ]]; then
^ ^
Finally, note that your condition was evaluated as true because it was evaluating if [ "string" ], which is true if string is not empty:
$ [ "a" ] && echo "yes"
yes
Test
$ cat a
#!/bin/bash
my_var="abcdefg";
if [[ "${my_var:0:5}" == "order" ]]; then
echo "value of my_var is ${my_var}."
elif [[ "${my_var:0:5}" == "abcde" ]]; then
echo "yeahaa"
else
echo "is not"
fi
$ ./a
yeahaa
Ok, i tested your code, you shoud such as the following code:
prefix="pre_order";
pre="pre_"
len=${#pre}
echo $len
if [[ "${prefix:0:len}" == "blahvlah" ]] ; then
echo "dddd"
fi;
Notes:
use == for string comparation
for ${} you should initilize a string variable before ${}
use len=${#pre} for lenght of string.
A POSIX-compliant way to test for a prefix is to attempt to remove the prefix, and compare the result to the original string. If the two are the same, the prefix is not present, the removal fails, and the expression expands to the original string.
prefix=foo
string=foobar
if [ "${string#$prefix}" = "$string" ]; then
printf "$string does not start with $prefix\n"
else
printf "$string starts with $prefix\n"
fi

Resources