This is bad code. getopt
is pretty much unusable¹. Use the getopts
shell builtin instead (it has two advantages: it can work, and it's available on all POSIX platforms).
What args=$(getopt optstring $*); set -- $args
does is:
- Split each command line argument at whitespace and replace it by the list of whitespace-delimited words.
- Take each of the resulting word and interpret it as a wildcard pattern. If the pattern matches at least one file, replace the pattern by the list of matching files.
- Pass the resulting list of words to the
getopt
command.
- Store the output of the
getopt
command in the variable args
. This is a string consisting of the command line arguments joined together with whitespace as the separator, and reordered to have options and their arguments, then --
, then non-option operands.
- Split this string at whitespace, interpret each word as a wildcard pattern, and replace the pattern by the list of matching files if there are any.
- Use the resulting list as the positional arguments.
In Bourne/POSIX-style shells, $foo
is the “split+glob” operator. You need double quotes to get the value of a variable: "$foo"
. But in zsh, $foo
works differently: it expands to the value of foo
except when foo
is empty. So in zsh you get a single positional parameter.
The first use of the split+glob operator could be avoided by writing getopt optstring "$@"
: this would pass the positional parameters exactly to getopt
. But when parsing the output of getopt
, splitting is unavoidable (you could disable globbing though), because getopt
uses spaces to separate arguments. The problem with getopt
is that the output is ambiguous: there's no way to distinguish a space that was in an argument from a space that getopt
added as a separator.
The right way to do this is with getopts
. It's robust and portable.
while getopts optstring OPTLET; do
# We got the option -$OPTLET
case $OPTLET in
…
esac
done
shift $((OPTIND-1))
# Now the positional parameters are just the non-option operands
¹ At least the BSD version. The GNU version adds features that make it usable.