4

I am new to bash scripting and I am trying to write a script with getopts so that when script.sh -sp is is invoked the URL and column and row count is printed out. And when script.sh -r option is invoked only the file type is printed.

Script :

#!/bin/bash

#define the URL URL='https://github.com/RamiKrispin/coronavirus/tree/master/data_raw' #define file name filename=$(basename "$URL") #dowload the file wget -q "${URL}"

while getopts ":sp:r" o; do case $o in

sp ) echo URL: $URL #print the URL address awk 'BEGIN{FS=","}END{print "COLUMN NO: "NF " ROWS NO: "NR}' $filename #print the column count and row count r ) file $filename #print the file type exit 1

esac done

Can anyone help me understand how to use getopts correctly?

ilkkachu
  • 138,973
Olaola
  • 55
  • note that getopt and getopts are different tools. You wrote getopt in the text but tagged the question with getopts. But you're also using getopts in the code, so I guess that's what you actually want. – ilkkachu Jan 02 '22 at 17:03
  • 1
    in any case, neither of them supports multi-character options. -sp would be the two options -s and -p. (or -s with the option-argument p, if -s took an opt-arg.) – ilkkachu Jan 02 '22 at 17:04

1 Answers1

7

getopts only supports single-character option names, and supports clustering: -sp is equivalent to passing -s and -p separately if -s doesn't take an argument, and it's the option -s with the argument p if -s takes an argument. This is the normal convention on Unix-like systems: after a single dash -, each character is a separate option (until an option that takes an argument); after a double dash --, everything (up to =) is the option name.

So getopts ":sp:r" o declares three options: -s and -r with no argument, and -p with an argument. You seem to only want two options and neither expects an argument, so the correct specification would be sr, and the usage would be script.sh script.sh -s or script.sh -r or script.sh -rs or script.sh -r -s etc.

while getopts sr o; do
  case $o in
    s)
      echo "URL: $URL" #print the URL address
      awk 'BEGIN{FS=","}END{print "COLUMN NO: "NF " ROWS NO: "NR}' -- "$filename" #print the column count and row count
      ;;
    r) file -- "$filename";; #print the file type
    \?) exit 3;; #invalid option
  esac
done
shift $((OPTIND - 1)) # remove options, keep non-option arguments
if [ $# -ne 0 ]; then
  echo >&2 "$0: unexpected argument: $1"
  exit 3
fi

The leading : says not to report unknown options to the user. Unknown options still cause $o to be ?. If you do that, you should print a message when $o is ?. And either way you should exit with a failure status if an option is unknown.

Other errors I fixed:

Note that it's spelled getopts, not getopt. There is a separate utility called getopt which has the same purpose but works differently and is rather harder to use. It doesn't support multiple-character options introduced by a single dash either, but it does support long options introduced by double dash.

ilkkachu
  • 138,973