Bash: Parse Options And Non-Options With Getopts
Parsing script or function options and non-option arguments is easy in Bash with
The code below will parse the function arguments and remove them so that $1 will refer to the first non-option argument (i.e. not starting with -). You would invoke it f.ex. as
getopts
but there are some catches, such as the need to reset OPTIND. We will se how to do it using getopts
, shift
, and case
.The code below will parse the function arguments and remove them so that $1 will refer to the first non-option argument (i.e. not starting with -). You would invoke it f.ex. as
latest_recur -x Hello -a '*.txt'
.
# Find the latest files under the current dir, recursively; options:
# -a list all, not only 30 latest
# - pattern passed to find's -name; ex.: "*.log.processed"
function latest_recur {
local show_all=
OPTIND=1
while getopts "ax:" opt; do
case $opt in
a) show_all=yes ;;
x) echo "You said: $OPTARG" ;;
\?) echo "Invalid option: -$OPTARG" >&2; return 1;;
esac
done
shift $((OPTIND-1))
if [ -z "$1" ]; then NAME_ARG=""; else NAME_ARG="-name $1"; fi
find -type f $NAME_ARG | xargs --no-run-if-empty stat --format '%Y :%y %n' | sort -nr | if [ -z "$show_all" ]; then head -n 30 -; else cat -; fi
}
- #5, #9 the variable used to store the flag must be defined/reset first
- #6 OPTIND is a global variable pointing to the next argument that getopts should parse; you must reset it manually (otherwise the next call to the function will ignore its arguments)
- #7 getopts parses one by one all the supported options (a, x here) and stores them into $opt;
- #10, #11 the value passed to the option (Hello, *.txt) is stored into the variable OPTARG
- #14 we must manually shift away the processed option arguments so that the first non-option argument ('*.txt') will become argument number 1 as you can see at #16; OPTIND is set by getopts
Getopts
can do quite a lot. It supports short options with or without arguments such as "-lht", "-l -h -t", "-l -I '*.swp'". It can also report/ignore unknown arguments etc., see its brief documentation and this small getopts tutorial. Briefly said, getopts takes opstring and varname; opstring is a list of letters optionally followed by ':' to indicate that that flag requires a value; varname is the name of the variable to store the flag name into. If you put : in front of the opstring (":ax:") then it will not complain about unknown options or missing arguments for options that require them.