shift 2 will remove the first 2 positional parameters so skip both --first and --second. You'd use shift 2 when processing an option that takes an argument (after having stored the value in $2). Here, for an option that doesn't take arguments, use shift, short for shift 1.
Instead of using the bash shell and the getopt command (here assumed to be the one from util-linux or compatible), you could also use a shell with builtin support for long option parsing such as zsh or ksh93:
#! /bin/zsh -
usage() {
print -ru2 "Usage: $ZSH_SCRIPT [--first] [--second]"
exit 1
}
zparseopts -D -F -A opt -- -first -second || usage
print "first=$+opt[--first] second=$+opt[--second]"
print -r Remaining args: "$@"
if (( $+opt[--second] )) print -- --second was given
#! /bin/ksh93 -
first=false second=false
while getopts '
[-?myscript 1.0]
[-author?Grass]
[+NAME?myscript - maybe do something first then second]
[+DESCRIPTION?Example description]
[=1:first?Do the first thing.]
[=2:second?Do the second thing.]
[ <extra-arg>... ]' opt; do
case $opt in
(1) first=true;;
(2) second=true;;
(*) exec -- "$0" '-?';;
esac
done
shift "$(( OPTIND - 1 ))"
print "first=$first second=$second"
print -r Remaining args: "$@"
if "$second"; then print -- --second was given; fi
With that one, you even get usage and man page for (almost) free:
$ ./myscript --help
Usage: ./myscript [ options ] [ <extra-arg>... ]
Help: ./myscript [ --help | --man ] 2>&1
OPTIONS
--first Do the first thing.
--second Do the second thing.
$ ./myscript --man
NAME
myscript - maybe do something first then second
SYNOPSIS
myscript [ options ] [ <extra-arg>... ]
DESCRIPTION
Example description
OPTIONS
--first Do the first thing.
--second Do the second thing.
IMPLEMENTATION
version myscript 1.0
author Grass
Beware all three (util-linux getopt, zsh's zparseopts and ksh93's getopts) parse options slightly differently between each other.
Note that [ $? != 0 ] (which should have better been written [ "$?" -ne 0 ]) is a command that negates the exit status of the previous command. To inverse the status, the ! keyword is more idiomatic:
if
! parsed_options=$(
getopt -o '' --long first,second -n 'testing' -- "$@"
)
then
echo>&2 Terminating...
exit 1
fi
eval "set -- $parsed_options"
Or here use the even more idiomatic parsed_options=$(...) || usage (with usage defined as a function that prints the usage on stderr and exits with failure and that can be reused any time wrong usage is detected).
shiftrather thanshift 2(since neither of your options expects an argument)?