How to write a bash script that takes optional input arguments?

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 ]
5

8 Answers

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.

7

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
6
if [ ! -z $1 ]
then : # $1 was given
else : # $1 was not given
fi
5

You can check the number of arguments with $#

#!/bin/bash
if [ $# -ge 1 ]
then $1
else foo
fi
0

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")}
2

This allows default value for optional 1st arg, and preserves multiple args.

 > cat mosh.sh set -- ${1:-xyz} ${@:2:$#} ; echo $* > mosh.sh xyz > mosh.sh 1 2 3 1 2 3 

For optional multiple arguments, by analogy with the ls command which can take one or more files or by default lists everything in the current directory:

if [ $# -ge 1 ]
then files="$@"
else files=*
fi
for f in $files
do echo "found $f"
done

Does not work correctly for files with spaces in the path, alas. Have not figured out how to make that work yet.

It's possible to use variable substitution to substitute a fixed value or a command (like date) for an argument. The answers so far have focused on fixed values, but this is what I used to make date an optional argument:

~$ sh co.sh
2017-01-05
~$ sh co.sh 2017-01-04
2017-01-04
~$ cat co.sh
DAY=${1:-$(date +%F -d "yesterday")}
echo $DAY

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like