How to write a bash script that takes optional input arguments?
Solution 1
You could use the default-value syntax:
somecommand ${1:-foo}
The above will, as described in Bash Reference Manual - 3.5.3 Shell Parameter Expansion [emphasis mine]:
If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted.
If you only want to substitute a default value if the parameter is unset (but not if it's null, e.g. not if it's an empty string), use this syntax instead:
somecommand ${1-foo}
Again from Bash Reference Manual - 3.5.3 Shell Parameter Expansion:
Omitting the colon results in a test only for a parameter that is unset. Put another way, if the colon is included, the operator tests for both parameter’s existence and that its value is not null; if the colon is omitted, the operator tests only for existence.
Solution 2
You can set a default value for a variable like so:
somecommand.sh
#!/usr/bin/env bash
ARG1=${1:-foo}
ARG2=${2:-'bar is'}
ARG3=${3:-1}
ARG4=${4:-$(date)}
echo "$ARG1"
echo "$ARG2"
echo "$ARG3"
echo "$ARG4"
Here are some examples of how this works:
$ ./somecommand.sh
foo
bar is
1
Thu 19 May 2022 06:58:52 ADT
$ ./somecommand.sh ez
ez
bar is
1
Thu 19 May 2022 06:58:52 ADT
$ ./somecommand.sh able was i
able
was
i
Thu 19 May 2022 06:58:52 ADT
$ ./somecommand.sh "able was i"
able was i
bar is
1
Thu 19 May 2022 06:58:52 ADT
$ ./somecommand.sh "able was i" super
able was i
super
1
Thu 19 May 2022 06:58:52 ADT
$ ./somecommand.sh "" "super duper"
foo
super duper
1
Thu 19 May 2022 06:58:52 ADT
$ ./somecommand.sh "" "super duper" hi you
foo
super duper
hi
you
Solution 3
if [ ! -z $1 ]
then
: # $1 was given
else
: # $1 was not given
fi
Solution 4
You can check the number of arguments with $#
#!/bin/bash
if [ $# -ge 1 ]
then
$1
else
foo
fi
Solution 5
please don't forget, if its variable $1 .. $n you need write to a regular variable to use the substitution
#!/bin/bash
NOW=$1
echo ${NOW:-$(date +"%Y-%m-%d")}
Abe
Updated on May 13, 2020Comments
-
Abe about 4 years
I want my script to be able to take an optional input,
e.g. currently my script is
#!/bin/bash somecommand foo
but I would like it to say:
#!/bin/bash somecommand [ if $1 exists, $1, else, foo ]
-
Ansel Halliburton over 12 yearsBash or POSIX? With Bash, there are more possibilities
-
Abe over 12 years@Pumbaa80 bash - I have updated the tags.
-
Vadzim over 8 years
-
Vadzim over 8 years
-
Joonho Park over 3 yearsI want to say that the this subject is not about the optional argument but a positional argument with default value. This terminology gives much confusion. "Optional argument" means it would be ok whether those arguments exist in the command line or not.
-
-
vmpstr over 12 yearsTechnically, if you pass in an empty string '' that might count as a parameter, but your check will miss it. In that case $# would say how many parameters were given
-
l0b0 over 12 yearsPlease note the semantic difference between the above command, "return
foo
if$1
is unset or an empty string", and${1-foo}
, "returnfoo
if$1
is unset". -
l0b0 over 12 years
-n
is the same as! -z
. -
jwien001 almost 10 yearsCan you explain why this works? Specially, what's the function/purpose of the ':' and '-'?
-
Jubbles almost 10 years@jwein001: In the answer submitted above, a substitution operator is used to return a default value if the variable is undefined. Specifically, the logic is "If $1 exists and isn't null, return its value; otherwise, return foo." The colon is optional. If it's omitted, change "exists and isn't null" to only "exists." The minus sign specifies to return foo without setting $1 equal to 'foo'. Substitution operators are a subclass of expansion operators. See section 6.1.2.1 of Robbins and Beebe's Classic Shell Scripting [O'Reilly] (shop.oreilly.com/product/9780596005955.do)
-
Vadzim over 8 yearsBrad's answer above proves that argument variables can also be substituted without intermediate vars.
-
Garren S over 7 years+1 for noting the way to use a command like date as the default instead of a fixed value. This is also possible:
DAY=${1:-$(date +%F -d "yesterday")}
-
Ohad Schneider over 7 years@Jubbles or if you don't want to buy an entire book for a simple reference... tldp.org/LDP/abs/html/parameter-substitution.html
-
sautedman over 7 yearsThis answer would be even better if it showed how to make the default be the result of running a command, as @hagen does (though that answer is inelegant).
-
Raffi Khatchadourian over 6 yearsAh, ok. The
-
confused me (is it negated?). -
Brad Parks over 6 yearsNope - that's just a weird way bash has of doing the assignment. I'll add some more examples to clarify this a bit... thanks!
-
DanielW about 5 yearsIf the subcommand possible takes multiple paramters, then:
somecommand ${@-foo}
-
Eliezer over 4 yearsI get different results using
-n
and! -z
so I would say that is not the case here. -
glenn jackman over 4 yearsbecause you failed to quote the variable,
[ -n $1 ]
will always be true. If you use bash,[[ -n $1 ]]
will behave as you expect, otherwise you must quote[ -n "$1" ]
-
Joonho Park over 3 yearsI am frustrated why this is optional argument. If you use $1 for a variable, it is positional argument not optional argument. If a command can receive an optional argument of -a -b -c then it should work with "command -a 10", "command -b ten", "command -c abc" and "command -a 7 -c aaa". If it works always with three arguments such as "command 10 ten abc", it is not a optional argument.
-
Anh-Thi DINH over 2 yearsFor ones like me: forget the ":" in the code, it's not required, replace it with your real commands!
-
Joonho Park over 2 yearsIt looks this is the limit of bash argument. Using python terminology, this is not optional, it is positional. It is just a positional argument with default values. Is there no really optional argument in bash?
-
Brad Parks over 2 yearsyou may be able to use getopts to get what you want - Here's 2 stackoverflow answers that go into greater detail: dfeault values and inside a function
-
mirekphd about 2 yearsNote also, that to confuse even more (with JSON/python dicts) no space is permitted anywhere, e.g. after the colon and/or after/before the dash... where is the principle of least astonishment here?:)
-
Brad Parks about 2 yearsgood point @mirekphd - I added an example showing how to put spaces in a default value. You can use single quotes if you want a literal value, or double quotes if you want variables to be interpolated