2046

I need to check the existence of an input argument. I have the following script

if [ "1ドル" -gt "-1" ]
 then echo hi
fi

I get

[: : integer expression expected

How do I check the input argument1 first to see if it exists?

Brad Parks
73.1k71 gold badges291 silver badges372 bronze badges
asked Jun 26, 2011 at 5:49
2
  • You did not tell us how you invoked this script. most likely, the first parameter was not an integral number. Commented Jul 3, 2023 at 10:46
  • How do I check the input argument1 first to see if it exists? : Do you mean "how do I check whether the argument 1 is non-empty?" or do you mean "how do I check whether the number of arguments is greater than zero?". Please clarify this in your question. Commented Jul 3, 2023 at 10:48

12 Answers 12

3388

It is:

if [ $# -eq 0 ]
 then
 echo "No arguments supplied"
fi

The $# variable will tell you the number of input arguments the script was passed.

Or you can check if an argument is an empty string or not like:

if [ -z "1ドル" ]
 then
 echo "No argument supplied"
fi

The -z switch will test if the expansion of "1ドル" is a null string or not. If it is a null string then the body is executed.

vallentin
26.4k6 gold badges69 silver badges92 bronze badges
answered Jun 26, 2011 at 5:55

16 Comments

I like to do it this way, in terse syntax and still POSIX acceptable. [ -z "1ドル" ] && echo "No argument supplied" I prefer one-liners, as they are easier for me; and it's also faster to check exit value, compared to using if
You probably want to add an exit 1 at the end of your echos inside the if block when the argument is required for the script to function. Obvious, but worth noting for completeness.
It is possible, though rarely useful, for the first argument to be initialized but empty; programname "" secondarg third. The $# check unambiguously checks the number of arguments.
For a noob, especially someone who comes from a non-scripting background, it is also important to mention some peculiarities about these things. You could have also mentioned that we need a space after the opening and the closing brace. Otherwise things do not work. I am myself a scripting noob (I come from C background) and found it the hard way. It was only when I decided to copy the entire thing "as is" that things worked for me. It was then I realized I had to leave a space after the opening brace and before the closing one.
and for optional args if [ ! -z "1ドル" ]; then ...
|
507

It is better to demonstrate this way

if [[ $# -eq 0 ]] ; then
 echo 'some message'
 exit 1
fi

You normally need to exit if you have too few arguments.

answered Nov 13, 2013 at 19:25

4 Comments

To know more about the difference between [ ] and [[ ]] see stackoverflow.com/questions/3427872/…
This answer is better than the accepted answer because 1. exiting with an error code is better than continuing with invalid data, and 2. [[ is normally more reasonable than [.
In my use case of executing the function directly from the command line, return 1 was a better choice (as exit 1 will close the terminal).
You could also send that error message to stderr rather than stdout, e.g. >&2 echo 'some message'
163

In some cases you need to check whether the user passed an argument to the script and if not, fall back to a default value. Like in the script below:

scale=${2:-1}
emulator @1ドル -scale $scale

Here if the user hasn't passed scale as a 2nd parameter, I launch Android emulator with -scale 1 by default. ${varname:-word} is an expansion operator. There are other expansion operators as well:

  • ${varname:=word} which sets the undefined varname instead of returning the word value;
  • ${varname:?message} which either returns varname if it's defined and is not null or prints the message and aborts the script (like the first example);
  • ${varname:+word} which returns word only if varname is defined and is not null; returns null otherwise.
answered Jul 31, 2014 at 18:55

3 Comments

The example above seems to use ${varname?message}. Is the extra : a typo, or does it change behavior?
Eki, the ":" is a builtin command and shorthand for /bin/true in this example. It represents a do-nothing command that basically ignores the arguments it is provided. It is essential in this test in order to keep the interpreter from trying to execute the contents of "$varname" (which you certainly do NOT want to happen). Also worth noting; you can test as many variables with this method as you wish. And all with specific error messages. i.e. : ${1?"First argument is null"} ${2?"Please provide more than 1 argument"}
I have bash scrip file name sitelog the show me nginx log file, I want to pass to it argument like sitelog -c to clear log file.
79

Try:

 #!/bin/bash
 if [ "$#" -eq "0" ]
 then
 echo "No arguments supplied"
 else
 echo "Hello world"
 fi
Koen.
27.2k7 gold badges86 silver badges80 bronze badges
answered Oct 21, 2013 at 4:20

6 Comments

Why do you need double-quotes for $# and 0?
No problem if we use without double-quotes as like $# and 0
This answer provides great starting point for a script I just made. Thanks for showing the else, too.
@user13107 double quoted variables in bash prevent globbing (i.e. expanding filenames like foo*) and word splitting (i.e. splitting the contents if the value contains whitespace). In this case it's not necessary to quote $# because both of those cases do not apply. Quoting the 0 is also not necessary, but some people prefer to quote values since they are really strings and that makes it more explicit.
re: "some people prefer to quote values since they are really strings" -eq is actually a numeric operator
All this superfluous quoting, used when not strictly necessary like here, raises redundant questions.
70

Only because there's a more base point to point out I'll add that you can simply test your string is null:

if [ "1ドル" ]; then
 echo yes
else
 echo no
fi

Likewise if you're expecting arg count just test your last:

if [ "3ドル" ]; then
 echo has args correct or not
else
 echo fixme
fi

and so on with any arg or var

answered Aug 2, 2018 at 21:00

1 Comment

At least allow for empty arguments: if [ "${3+set}" ]; then... to check for at least 3 args, working correctly even if they 3rd arg is empty.
48

Another way to detect if arguments were passed to the script:

((!$#)) && echo No arguments supplied!

Note that (( expr )) causes the expression to be evaluated as per rules of Shell Arithmetic.

In order to exit in the absence of any arguments, one can say:

((!$#)) && echo No arguments supplied! && exit 1

Another (analogous) way to say the above would be:

let $# || echo No arguments supplied
let $# || { echo No arguments supplied; exit 1; } # Exit if no arguments!

help let says:

let: let arg [arg ...]

 Evaluate arithmetic expressions.
 ...
 Exit Status:
 If the last ARG evaluates to 0, let returns 1; let returns 0 otherwise.
Iulian Onofrei
9,82611 gold badges72 silver badges118 bronze badges
answered Jul 20, 2013 at 10:26

4 Comments

-1 this might be the worst method if validating existence of an argument.. plus it can trigger history substitution and potentially do bad things.
instead of exit which kills my zsh process, I use return which does not kill it
Why would ((!$#)) trigger history substitution?
What's about 3rd input argument , e.g I have ffmpeg script to downscale videos, but sometimes I want to cut part of it using -ss parameter as 3rd argument on my script, if that arg not presented the clip won't be cut. if [ -z "3ドル" ]; then
37

I often use this snippet for simple scripts:

#!/bin/bash
if [ -z "1ドル" ]; then
 echo -e "\nPlease call '0ドル <argument>' to run this command!\n"
 exit 1
fi
answered Dec 29, 2017 at 17:55

2 Comments

So, this is to be used in you need only one argument?
@Danijel No, this is testing if there is an argument in the first position. You could have a 2ドル or a 3ドル argument (0ドル is the script name being run). This simply ignores any other arguments passed.
28

Using double square-bracket is always a good practice

#!/bin/bash
if [[ $# -gt 0 ]]; then
 echo "Get arguments: $@"
else
 echo "No arguments were provided."
fi
  • $# returns number of arguments.
  • $@ returns the actual arguments.

You can safely use [[ ... ]] in most cases, unless you specifically need to use #!/bin/sh.

In this case, double [[ ... ]] or single [ ... ] square bracket makes no difference.

TL;DR

But [[ ... ]] allows you to:

  • Escape special characters like <, >, and |.
  • Use regular expressions for string matching.
  • Use logical operators && and || within the brackets.

Let's consider you want pass a text file:

# This works:
if [[ 1ドル == *.txt ]]; then
 echo "From double: 1ドル"
fi
# This won't!
if [ 1ドル == *.txt ]; then
 echo "From single: 1ドル"
fi
FisNaN
2,9152 gold badges29 silver badges43 bronze badges
answered Mar 22, 2022 at 15:28

3 Comments

Why is this more modern?
@AlJohri Here are some answers to your question: stackoverflow.com/q/669452/2192488 and superuser.com/q/1533900/219226.
Point of order: [[ is a non-POSIX extension keyword that is available only in certain shells. It's been in ksh, bash, and zsh since last century, but availability in other shells is still spotty. For example, on my system ash and dash both say [[: not found.
12

If you'd like to check if the argument exists, you can check if the # of arguments is greater than or equal to your target argument number.

The following script demonstrates how this works

test.sh

#!/usr/bin/env bash
if [ $# -ge 3 ]
then
 echo script has at least 3 arguments
fi

produces the following output

$ ./test.sh
~
$ ./test.sh 1
~
$ ./test.sh 1 2
~
$ ./test.sh 1 2 3
script has at least 3 arguments
$ ./test.sh 1 2 3 4
script has at least 3 arguments
answered Sep 13, 2017 at 16:45

Comments

4

As a small reminder, the numeric test operators in Bash only work on integers (-eq, -lt, -ge, etc.)

I like to ensure my $vars are ints by

var=$(( var + 0 ))

before I test them, just to defend against the "[: integer arg required" error.

Peter Mortensen
31.5k22 gold badges110 silver badges134 bronze badges
answered Oct 24, 2013 at 22:39

2 Comments

Neat trick, but please note: due to bash's inability to handle floats in arithmetic, this method can cause a syntax error and return non-zero which would be a hindrance where errexit is enabled. var=$(printf "%.0f" "$var") can handle floats but suffers from the non-zero exit when given a string. If you don't mind an awk, this method I use seems to be the most robust for enforcing an integer: var=$(<<<"$var" awk '{printf "%.0f", 0ドル}'). If var is unset, it defaults to "0". If var is a float, it is rounded to the nearest integer. Negative values are also fine to use.
The +0 does not serve any purpose in that expression. Perhaps you were thinking of $(( $var +0 )) which is more portable. The point of the +0 is so that it will still work when $var is empty, but if you write $(( var )) then it is the arithmetic engine that's fetching the value of var and then evaluating that as a subexpression, so in $((var+0) the subexpression has already succeeded or failed before the +0 is attempted. In fact, bash guarantees that $((var)) will evaluate to 0 when var is empty, whereas leaving out the $ before var is a syntax error in ksh.
2

one liner bash function validation

myFunction() {
 : ${1?"forgot to supply an argument"}
 if [ "1ドル" -gt "-1" ]; then
 echo hi
 fi
}

add function name and usage

myFunction() {
 : ${1?"forgot to supply an argument ${FUNCNAME[0]}() Usage: ${FUNCNAME[0]} some_integer"}
 if [ "1ドル" -gt "-1" ]; then
 echo hi
 fi
}

add validation to check if integer

to add additional validation, for example to check to see if the argument passed is an integer, modify the validation one liner to call a validation function:

: ${1?"forgot to supply an argument ${FUNCNAME[0]}() Usage: ${FUNCNAME[0]} some_integer"} && validateIntegers 1ドル || die "Must supply an integer!"

then, construct a validation function that validates the argument, returning 0 on success, 1 on failure and a die function that aborts script on failure

validateIntegers() {
 if ! [[ "1ドル" =~ ^[0-9]+$ ]]; then
 return 1 # failure
 fi
 return 0 #success
}
die() { echo "$*" 1>&2 ; exit 1; }

Even simpler - just use set -u

set -u makes sure that every referenced variable is set when its used, so just set it and forget it

myFunction() {
 set -u
 if [ "1ドル" -gt "-1" ]; then
 echo hi
 fi
}
answered Jan 26, 2020 at 20:03

Comments

-3

In my case (with 7 arguments) the only working solution is to check if the last argument exists:

if [[ "7ドル" == '' ]] ; then
 echo "error"
 exit
fi
Matthew
1,7002 gold badges14 silver badges27 bronze badges
answered Sep 22, 2020 at 15:12

3 Comments

This is not true. 7ドル is the 7th argument (8th if you count 0ドル which is the script name), so this does not check if the last argument exists, it checks if the 7th argument exists.
I do agree that this is not a solution to the question, and a sub-optimal solution to a different (and probably avoidable) problem. Seven positional arguments seems heavy. In addition, exit without exit status will return the exit status of echo "error", which I expect to be zero. Recommend shellcheck and set -euo pipefail. I'm going to stop now...
While not a unique answer, it is similar to other accepted answers that have several upvotes. It seems that the author may not be a native English speaker, and likely meant that in their case of 7 arguments, this was a working solution. I've edited the answer to reflect that. Suggestions from @JackWasey should definitely be taken into consideration.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.