Question

I have the following script that I call from my .bash_profile:

# Set directories based on current path
__set_dirs() {
    currdir=`pwd`
    if [[ ${currdir} =~ "\/path\/to\/main\/(.*)\/working\/([a-z]+)(/?.*)" ]]
    then
        ws=${BASH_REMATCH[1]}
        subdirs=${BASH_REMATCH[3]}
        stgdir=${ts}/${ws}/STAGING${subdirs}
    else
        echo "${currdir} is not a workspace"
        stgdir=""
    fi
}

# Update local version with staging version
upd() {
    __set_dirs
    if [[ -n ${stgdir} ]]
    then
        __overwrite=0
        while getopts "o" opt
        do
            case $opt in
                o)
                    __overwrite=1
                    ;;
                \?)
                    echo "Invalid option: -$OPTARG" >&2
                    ;;
            esac
        done

        echo "Updating ${currdir} with latest from ${stgdir}..."
        if [ ${__overwrite} -eq 0 ]
        then
            update -r ${stgdir} ${currdir}
        else
            echo "Overwriting all local changes!"
            update -r -w ${stgdir} ${currdir}
        fi
    fi
    unset __overwrite
}

When I execute

> upd -o

The flag is completely ignored--I never see the message "Overwriting all local changes!". Have I missed something somewhere?

UPDATE: It does work, but only the first time I run the script. From the second time on, the flag gets ignored.

Was it helpful?

Solution

All right, figured it out:

After rifling through the man page for getopts, I found this tidbit (emphasis mine):

Each time it is invoked, getopts places...the index of the next argument to be processed into the variable OPTIND. OPTIND is initialized to 1 each time the shell or a shell script is invoked.... The shell does not reset OPTIND automatically; it must be manually reset between multiple calls to getopts within the same shell invocation if a new set of parameters is to be used.

Since I only run the script once from by .bashrc, OPTIND only gets initialized once. The first time I run the function, everything's hunky dory. The second time on, OPTIND is set to 2 and getopts doesn't find anything there, so it moves on.

Armed with this knowledge, I modified upd() to reset OPTIND to 1:

upd() {
    __set_dirs
    if [[ -n ${stgdir} ]]
    then
         __overwrite=0
         OPTIND=1
         while getopts "o" opt
...

That fixed it. OPTIND: more important than you'd think.

OTHER TIPS

getopts acts on the parameters passed into your function, so in your case you have to call the upd() function with "$@", to pass all the command line parameters into your function.

eg:

test() {
  while getopts "o" opt; do
    case $opt in
    o)
      echo o
    ;;
    \?)
      echo "Invalid option: -$OPTARG" >&2
    ;;
    esac
  done
}
test # this wont work as $1, $2, ... are not set
test $@ # this will work as you pass along the command line parameters

Edit

I overlooked the .bashrc part, if I source the example above, into my running shell, then test -o works as expected.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top