Search code examples
bashshellgetopts

Bash script - how to read file line by line while using getopts


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?


Solution

  • 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