4

I want to do two things in this script: 1) pass a file name to the script 2) pass options to the script

example 1: $./test_script.sh file_name_to_be_read pass only file names to script

example 2: $./test_script.sh -a -b file_name_to_be_read pass file name and options to script

I am able to get example 1 to work using the following codes:

while read -r line ; do
    echo $line
done

In example 2, I want to add additional flags like these:

while getopts "abc opt; do
    case "$opt" in
    a) a=1
       echo "a is enabled"
       ;;
    b) b=1
       echo "b is enabled"
       ;;
    esac
done

but how do I make it so that the file_name to be mandatory and be used with or without options?

user97662
  • 942
  • 1
  • 10
  • 29
  • 1
    a side note: the lines read by `while read -r line` will have any leading/trailing tabs and spaces removed. To truly read lines of a file verbatim, use `while IFS= read -r line` – glenn jackman Dec 14 '15 at 20:49

1 Answers1

4

getopts only parses options (arguments starting with -); the other arguments are left alone. The parameter OPTIND tells you the index of the first argument not yet looked at; typically you discard the options before this.

while getopts "ab" opt; do
    case "$opt" in
    a) a=1
       echo "a is enabled"
       ;;
    b) b=1
       echo "b is enabled"
       ;;
    esac
done

shift $((OPTIND - 1))

echo "$# arguments remaining"
for arg in "$@"; do
    echo "$arg"
done

The preceding, if called as bash tmp.bash -a -b c d e, produces

$ bash tmp.bash -a -b c d e
a is enabled
b is enabled
3 arguments remaining:
c
d
e
chepner
  • 497,756
  • 71
  • 530
  • 681
  • I found this explanation of shift ((OPTIND -1)): shift $((OPTIND-1)) (note OPTIND is upper case) is normally found immediately after a getopts while loop. $OPTIND is the number of options found by getopts. shift "$((OPTIND-1))" – user97662 Dec 14 '15 at 20:34
  • `OPTIND` remains `1` if first argument is not starting with `-` .e.g. `bash tmp.bash foo -a -b -c` – anubhava Dec 14 '15 at 20:39
  • In some sense, `getopts` "finds" the first non-option argument; it's the one that causes `getopts` to have a non-zero exit status, terminating the loop. The resulting `shift 0` leaves the argument list unmodified. – chepner Dec 14 '15 at 20:40