Używam następujące linie (nadzieję, że to jest najlepsze praktyki, jeśli nie poprawcie mnie proszę) do obsługi opcji wiersza polecenia:Bash - getopts - masa argumenty (operandów) na pierwszym miejscu w linii argumentu polecenia przechodzące
#!/usr/bin/bash
read -r -d '' HELP <<EOF
OPTIONS:
-c Enable color output
-d Enable debug output
-v Enable verbose output
-n Only download files (mutually exclusive with -r)
-r Only remove files (mutually exclusive with -n)
-h Display this help
EOF
# DECLARE VARIABLES WITH DEFAULT VALUES
color=0
debug=0
verbose=0
download=0
remove=0
OPTIND=1 # Reset in case getopts has been used previously in the shell
invalid_options=(); # Array for invalid options
while getopts ":cdvnrh" opt; do
echo "Actual opt: $opt"
case $opt in
c)
color=1
;;
d)
debug=1
;;
v)
verbose=1
;;
n)
download=1
;;
r)
remove=1
;;
h)
echo "$HELP"
exit 1
;;
\?)
invalid_options+=($OPTARG)
;;
*)
invalid_options+=($OPTARG)
;;
esac
done
# HANDLE INVALID OPTIONS
if [ ${#invalid_options[@]} -ne 0 ]; then
echo "Invalid option(s):" >&2
for i in "${invalid_options[@]}"; do
echo $i >&2
done
echo "" >&2
echo "$HELP" >&2
exit 1
fi
# SET $1 TO FIRST MASS ARGUMENT, $2 TO SECOND MASS ARGUMENT ETC
shift $((OPTIND - 1))
# HANDLE CORRECT NUMBER OF MASS OPTIONS
if [ $# -ne 2 ]; then
echo "Correct number of mass arguments are 2"
echo "" >&2
echo "$HELP" >&2
exit 1
fi
# HANDLE MUTUALLY EXCLUSIVE OPTIONS
if [ $download -eq 1 ] && [ $remove -eq 1 ]; then
echo "Options for download and remove are mutually exclusive" >&2
echo "$HELP" >&2
exit 1
fi
echo "color: $color"
echo "debug: $debug"
echo "verbose: $verbose"
echo "download: $download"
echo "remove: $remove"
echo "\$1: $1"
echo "\$2: $2"
Jeśli wzywam drogę skryptu mass arguments (te, które nie są przełączniki lub argumenty dla przełączników) są ostatnie argumenty wszystko działa poprawnie:
$ ./getopts.sh -c -d -v -r a b
Actual opt: c
Actual opt: d
Actual opt: v
Actual opt: r
color: 1
debug: 1
verbose: 1
download: 0
remove: 1
$1: a
$2: b
problem jest, gdy chcę wywołać skrypt więc argumenty masowe są pierwsze (lub gdzieś w środku przełączników, które d • Nie używać argumentów)
$ ./getopts.sh a b -c -d -v -r
Correct number of mass arguments are 2
OPTIONS:
-c Enable color output
-d Enable debug output
-v Enable verbose output
-n Only download files (mutually exclusive with -r)
-r Only remove files (mutually exclusive with -d)
-h Display this help
lub
$ ./getopts.sh -c a b -d -v -r
Actual opt: c
Correct number of mass arguments are 2
OPTIONS:
-c Enable color output
-d Enable debug output
-v Enable verbose output
-n Only download files (mutually exclusive with -r)
-r Only remove files (mutually exclusive with -d)
-h Display this help
myślę, że to powinno być OK według (POSIX) normy, bo po składni, która jest w zasadzie taka sama działa zgodnie z oczekiwaniami w moim systemie:
$ cp test1/ test2/ -r
$ cp test1/ -r test2/
mam szukać w Internecie, ale jedyną rzeczą, która była blisko mojego problemu było this one związane C
Twoje obserwacje są poprawne: getopts zwraca kod zakończenia, gdy napotkany zostanie pierwszy argument nie będący opcją, więc kończy się pętla while. Wierzę, że ['getopt'] (http://man.cx/getopt) może działać w bardziej elastyczny sposób. –
@glennjackman istnieją zalecenia dotyczące używania getopts przez getopt. AFAIK getopt jest uważany za przestarzały. –
Nie wierzę, że getopt jest przestarzały. getopts jest łatwiejszy w użyciu (IMO: to jest to, czego używam), ale zmusza cię do umieszczenia opcji przed wymaganymi parametrami i nie możesz użyć opcji -longoptions. –