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

BashArgumentsParameter Passing

Bash Problem Overview


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 ]

Bash Solutions


Solution 1 - Bash

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 - Bash

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 - Bash

if [ ! -z $1 ] 
then 
    : # $1 was given
else
    : # $1 was not given
fi

Solution 4 - Bash

You can check the number of arguments with $#

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

Solution 5 - Bash

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

Solution 6 - Bash

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 
 

Solution 7 - Bash

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.

Solution 8 - Bash

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAbeView Question on Stackoverflow
Solution 1 - BashItay PerlView Answer on Stackoverflow
Solution 2 - BashBrad ParksView Answer on Stackoverflow
Solution 3 - BashIrit KatrielView Answer on Stackoverflow
Solution 4 - BashDennisView Answer on Stackoverflow
Solution 5 - BashhagenView Answer on Stackoverflow
Solution 6 - BashmoshView Answer on Stackoverflow
Solution 7 - BashJesse GlickView Answer on Stackoverflow
Solution 8 - BashGarren SView Answer on Stackoverflow