Why do I get unary operator expected? - bash

So I am busy creating a rm function or I guess that is what it's called.
After executing the script and typing rm I get this error:
bash: [: ==: unary operator expected
My code is:
rm(){
if[ "$#" == "-u" ];
then
echo "Do something amazing."
else
echo "Boring"
}
I have even tried replacing the == with -eq but I still get the same error.
How to fix this?
P.S. when I type rm -u I don't get the error the code runs fine.

"$#" expands to all the arguments of the function, each separately requoted. If there are no arguments, it expands to an empty string, and the if statement becomes.
if [ == "-u" ]
which is not valid because there's nothing before ==. You would also get an error if you gave multiple arguments to the function; if you do rm -x -y it becomes
if [ "-x" "-y" == "-u" ]
Use "$*" instead of "$#" to get all the arguments as a single string.

Related

Why is my zshrc function not working when adding arguments?

I am trying to make a function to start, stop or restart from any directory
The code works fine without any arguments but when adding any argument I get the webserver:6: = not found error, when testing the variables everything looks like it should work
function webserver {
#echo $USERNAME
'echo $1
if [ "$1" != "" ]
then
if [ "$1" == "start"]
then
/Users/$USERNAME/start.sh
fi
if [ "$1" == "stop"]
then
/Users/$USERNAME/stop.sh
fi
if [ "$1" == "restart"]
then
/Users/$USERNAME/restart.sh
fi
else
echo "Invalid arguments! Valid arguments are : start stop restart"
fi
}
Why is this code not working?
There's a single-quote before the echo $1 command, which'll cause different trouble. Is that a typo?
The mains problem is that your comparison syntax is wrong; in a [ ] test, use a single = for string equality test, and you need spaces between each syntactic element, including before the final ].
if [ "$1" == "start"] # Bad, will give errors
if [ "$1" = "start" ] # Good, will work as expected
Also, I'd replace that series of if statements with a either a case statement, or a single if ... elif ... elif, since only one branch will ever be taken.
case "$1" in
start)
/Users/$USERNAME/start.sh ;;
stop)
/Users/$USERNAME/stop.sh ;;
restart)
/Users/$USERNAME/restart.sh ;;
*) # This is the case equivalent of "else"
echo "Invalid arguments! Valid arguments are : start stop restart" ;;
esac
like Gordon said, the syntax for zsh is wrong with only one [ ].
according to "==" logical operator and zsh version 5.7.x (installed using Homebrew)
Simple answer: a == is a logical operator only inside [[ … ]] constructs.
And it works also in ksh and bash.
When used outside a [[ … ]] construct a =cmd becomes a filename expansion operator but only in zsh
$ echo ==
zsh: = not found

multiple conditions in bash shell

I have this piece of code in Bash,
The goal is to compare two files and if files matches and also no force argument is passed, then exit.
Other way it should continue...
But I got this error [: !=: unexpected operator when I run with no argument and script is not stopped as expected,
When I pass force argument it works OK.
Any Idea please ?
if cmp -s file1 file2 && [ $1 != "-f" ] ; then
"do something"
exit 1
else "do something"
fi
[ ... ] is just a normal command, essentially equivalent to test. As such, if you pass an unquoted empty variable (like $1 when no arguments are provided to your program), it will try to run [ != "-f" ], which gives that error, since you need two sides to compare with !=.
To solve this, you can either use [[ ... ]] (which requires bash, not being POSIX compatible), which does not make unquoted variables "disappear", or you can also quote your variable to keep it POSIX compatible:
cmp -s file1 file2 && [[ $1 != "-f" ]]
cmp -s file1 file2 && [ "$1" != "-f" ]

Bash if statement not working properly

I have a bash statement to test a command line argument. If the argument passed to the script is "clean", then the script removes all .o files. Otherwise, it builds a program. However, not matter what is passed (if anything), the script still thinks that the argument "clean" is being passed.
#!/bin/bash
if test "`whoami`" != "root" ; then
echo "You must be logged in as root to build (for loopback mounting)"
echo "Enter 'su' or 'sudo bash' to switch to root"
exit
fi
ARG=$1
if [ $ARG == "clean" ] ; then
echo ">>> cleaning up object files..."
rm -r src/*.o
echo ">>> done. "
echo ">>> Press enter to continue..."
read
else
#Builds program
fi
Answer for first version of question
In bash, spaces are important. Replace:
[ $ARG=="clean" ]
With:
[ "$ARG" = "clean" ]
bash interprets $ARG=="clean" as a single-string. If a single-string is placed in a test statement, test returns false if the string is empty and true if it is non-empty. $ARG=="clean" will never be empty. Thus [ $ARG=="clean" ] will always return true.
Second, $ARG should be quoted. Otherwise, if it is empty, then the statement reduces to `[ == "clean" ] which is an error ("unary operator expected").
Third, it is best practices to use lower or mixed case for your local variables. The system uses upper-case shell variables and you don't want to accidentally overwrite one of them.
Lastly, with [...], the POSIX operator for equal, in the string sense, is =. Bash will accept either = or == but = is more portable.
first:
Every string must double quoted or will error absent argument.
second:
for string used only = or != not a == and also -n and -z commands.
third:
you may combine conditions by -a and -o commands but newer used enclose in () yous conditions so not to get error. Logical operators acts through operators presidence, fist calculate -o operator and then -a! For example
[ -n "$1" -a $1 = '-h' -o $1 = '--help' ] && { usage; exit 0; }
will work when passed to script at least 1 argument and is -h or --help. All spaces must be!!! Bush do short cycle logical evaluations. So don't trouble for case when $1 don't exist in second condition because of result of this expression is determined in first one. next don't calculate in this case. But if your argument may contains space symbols you need it double quote. You must do it also in command line too! Else you get error in script or split your arguments in two or more parts.
Operator == isn't used in test. For numbers(not siring) used -eq or -ne commands. See man 1 test for full descriptions. test EXPRESSION... equivalent of [ EXPRESSIONS... ]. More shirt form of test.

Bash Unary Operator Expected

Okay, so within my script (this is my first time working with Bash) I am being met with two unary operator expected errors. The code itself is actually working fine, but it's presenting me with these errors at runtime:
[: !=: unary operator expected
For the line:
if [ ${netmask[1]} != "" ]; do
So for the first error, it's thrown when ${netmask[1]} is "" (null). I have tried multiple ideas and still can't get it to work without returning that error in the process.
I solved it by adding quotation marks (grrr)
if [ "${netmask[1]}" != "" ]; do
If you want to check for the null value for a variable, use the -z operator:
if [ -z "${netmask[1]}" ]; then
On example:
VAR=""
if [ -z "$VAR" ]; then
echo This will get printed
fi
Please note the parentheses around the variable: "$VAR".

"" on $1, why does bash behave like this?

if a script has
if [ $1 == "-?" ]; then #line 4
echo "usage: ...."
fi
when the script get runs without any parameter, it will complain that
./script.sh: line 4: [: ==: unary operator expected
but if instead
if [ "$1" == "-?" ]; then #line 4
echo "usage: ...."
fi
then everything's fine
why is that?
thanks
If the first argument is missing or empty, your first script evaluates to:
if [ == "-?" ] ; then
... which is a syntax error. As you noticed, to prevent that you need to make use of "", then it evaluates to:
if [ "" == "-?" ] ; then
AFAIK this is due to the way the original Bourne shell was working. You should make it a habit of enclosing variables in "" to also work correctly with arguments that have spaces in it. For example, if you would call your script like this:
./myScript "first argument has spaces"
Then your first script would evaluate to:
if [ first argument has spaces == "-?" ] ; then
which is also a syntax error. Also things like rm $1 will not do what you want if you pass filenames with spaces. Do rm "$1" instead.
Because [ replaces the values before executing. [[ doesn't, so will work as expected.

Resources