Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I'm working on a bash script and i need to implement "options". How can i do that with bash?

my goal is tu run script the following way: /myscript.sh -d "/var/log/" -c "test"

what i've tried:

while shift; do
        case $1 in
                -d)
                        shift&&DIR="$1"||die
                ;;
                -c)
                        shift&&COMMAND="$1"||die
                ;;
        esac
done

echo "$DIR"
echo "$COMMAND"
share|improve this question
    
And what exactly happens when you try this? –  Dennis Jan 25 '13 at 15:34
    
print only the -c) case –  teslasimus Jan 25 '13 at 15:40

4 Answers 4

up vote 2 down vote accepted

To expand @choroba's answer, here's an example of how to use getopts:

# parse the flag options (and their arguments)
while getopts c:d: OPT; do
    case "$OPT" in
      d)
        DIR="$OPTARG" ;;
      c)
        COMMAND="$OPTARG" ;;
      [?])
        # got invalid option
        echo "Usage: $0 [-d directory] [-c command]" >&2
        exit 1 ;;
    esac
done

# get rid of the just-finished flag arguments
shift $(($OPTIND-1))

Note that after shifting off the flag arguments, any "regular" arguments will remain. So at that point you could either deal with them (e.g. ... for arg in "$@"; do ...) or if your script doesn't take them just gripe if you get any (if [ $# -gt 0 ]; then echo "Usage ...).

share|improve this answer

As choroba already said, getopts is a better approach.

In your case, you could use:

getopts c:d: d || die
DIR=$OPTARG
getopts c:d: c || die
COMMAND=$OPTARG

to achieve what you're trying to do with the while loop.

The string c:d: specifies the possible switches. The colon means that the switch requires an argument.

The problem with your approach is that you call shift before analyzing the first argument, discarding it in the process.

To fix this, change the while loop to the following:

while true; do
        case $1 in
                -d)
                        shift&&DIR="$1"||die
                ;;
                -c)
                        shift&&COMMAND="$1"||die
                ;;
        esac
        shift || break
done
share|improve this answer

Your mistake is that you're shifting at the top of the loop, tossing the first argument before you've examined it. This is what I think you probably meant:

#!/bin/bash
while (( "$#" )); do
   case $1 in
      -d)
         shift&&DIR="$1"||die
         ;;
      -c)
         shift&&COMMAND="$1"||die
         ;;
   esac
   shift
done

echo "$DIR"
echo "$COMMAND"
share|improve this answer
    
die? bash is not Perl –  glenn jackman Jan 25 '13 at 19:04
    
@glennjackman Good comment. I didn't catch that as a possible problem. (Note the OP explains that the complaint is that it only prints the -c) case.) I assumed die was probably an alias -- or at least, that whatever it was didn't matter to the question. –  Nicole Hamilton Jan 25 '13 at 19:24
    
right, I commented to the wrong person... –  glenn jackman Jan 25 '13 at 19:25

The usual approach is to use getopts.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.