You could do it manually, but using getopt
would be more useful moving forward. Consider for example:
#!/bin/bash
# Prints first set of lines from named files.
# $1 NUM Number of lines to print
# $2 DIR Directory
headrc() {
eval set -- $(getopt --name "${FUNCNAME[0]}" --options h --longoptions help -- "${@}")
while [[ "${1}" != "--" ]]; do
case "${1}" in
-h | --help)
printf "Usage: ${FUNCNAME[0]} [-h|--help] <args>\n"
return 1
;;
*)
printf "Unknown option: ${1}\n"
;;
esac
shift # Shift off option
done
shift # Shift off --
local -r num="${1}"
local -r dir="${2}"
find "${dir}" \( -name \*.org -o -name \*.texi \) | xargs head -n "${num}";
}
The getopt
tool takes the existing arguments (${@}
) and the options that you give it, and reorders them such that all the options come first, then a --
, then everything else. The --options
option specifies the single-character options and the --longoptions
specifies the "long" (multi-character) options.
For example:
$ getopt --options fh --longoptions file,help -- a b c -f d e --help g
-f --help -- 'a' 'b' 'c' 'd' 'e' 'g'
Note that getopt
supports options with parameters, but since you don't need that here, I didn't cover that aspect of the tool.
The eval set --
updates the arguments to the given values, rewriting what the function sees as its arguments to the output of getopt
.
The while
loop processes the options; the options stop when it encounters --
. If is see -h
or --help
, it prints a help message and returns. Each time it processes the loop it uses shift
to "shift off" the first argument.
Once it finds the --
it stops looping, and shifts off that argument.
You're now left with everything that came after the options, so you can use the positional arguments like you did before.