I am trying to create a script using getopts
that would work as wc
. the problem is that I get stuck when I use two switches together. The script:
while getopts l:w:c: choice
do
case $choice in
l) wc -l $OPTARG;;
w) wc -w $OPTARG;;
c) wc -c $OPTARG;;
?) echo wrong option.
esac
done
When I run this script with ./script.sh -l file
it works, but when I use ./script -wl file
it just goes into an infinite loop. Can anyone please explain what's going on and how to fix it?
You're using it incorrectly. As per the getopts manual :
If a letter is followed by a colon , the option is expected to have an argument.
And in your example you're not passing argument for -w
and -l
options;
Correct usage is:
./script -w file1 -l file2
Which will process both options correctly.
Otherwise to support an option without argument just use it without colon like this:
while getopts "hl:w:c:" choice
Here option h
will not need an argument but l, w, c will support one.
You need to build the options in the case statement and then execute wc
:
# Set WC_OPTS to empty string
WC_OPTS=();
while getopts lwc choice
do
case $choice in
l) WC_OPTS+='-l';;
w) WC_OPTS+='-w';;
c) WC_OPTS+='-c';;
?) echo wrong option.
esac
done
# Call wc with the options
shift $((OPTIND-1))
wc "${WC_OPTS[@]}" "$@"
To add to the other comments . . . the version of wc
that I have handy seems to handle its options like this:
#!/bin/bash
options=()
files=()
while (( $# > 0 )) ; do
if [[ "$1" = --help || "$1" = --version ]] ; then
wc "$1" # print help-message or version-message
exit
elif [[ "${1:0:1}" = - ]] ; then
while getopts cmlLw opt ; do
if [[ "$opt" = '?' ]] ; then
wc "$1" # print error-message
exit
fi
options+="$opt"
done
shift $((OPTIND-1))
OPTIND=1
else
files+="$1"
shift
fi
done
wc "${options[@]}" "${files[@]}"
(The above could be refined further, by using a separate variable for each of the five possible options, to highlight the fact that wc
doesn't care about the order its options appear in, and doesn't care if a given option appears multiple times.)
Got a workaround.
#!/bin/bash
if [ $# -lt 2 ]
then
echo not a proper usage
exit
fi
file=$2
while getopts wlc choice
do
case $choice in
l) wc -l $file
;;
w) wc -w $file
;;
c) wc -c $file
;;
?) echo thats not a correct choice
esac
done
I think I got obsessed with OPTARG, thanks everyone for your kind help
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.