1

I'm trying to write a script in a way that makes it simple to add future command line args. I'm using getopts and that works well. However, I'm running into issues with the case statement.

args=`getopt lLo:t: $*`
if [ $? -ne 0 ]
then
   echo "Usage: Default error message"
fi

while [ "$#" -eq 3 ] || [ "$#" -eq 5 ]
do 
   if [ "$1" != "-o" ] && [ "$1" != "-t" ]
   then
      echo "\nInvalid argument sequence."
      exit 1
   fi

   case "$1" in
   (-o)
      shift
      VAR1="$1"
      shift
      ;;
   (-t)
      shift
      VAR2="$1"
      shift
      ;;
   (*)
      LAST_VAR="$1"
      ;;
   (--) shift; break;;
 esac
done

If I then echo $LAST_VAR it is null. Any ideas? Is there a better way to do this?

1
  • @l0b0 Thanks! My actual code has the spaces there, and I didn't know I could exclude the ( in case matching.
    – nullByteMe
    Commented May 23, 2013 at 13:45

1 Answer 1

2

Some findings:

  • You need spaces around each [ and ] (line 2). See help [.
  • You don't need ( in case matchings. See help case.
  • You can use VAR1="$2" and shift 2 instead of two separate shifts. See help shift.
  • You want to put the -- case before *, and move the break to the * case.
  • Follow the logic backwards: LAST_VAR will be set if $1 is neither -o nor -t. Before that you exit if $1 is neither -o nor -t. So LAST_VAR can never be set.

I would suggest looking at some getopt examples for some ideas. Shameless plug for some tested code:

# Process parameters
params="$(getopt -o d:e:fshv \
    -l diff:,exclude:,force,skip-existing,help,verbose \
    --name "$cmdname" -- "$@")"

if [ $? -ne 0 ]
then
    usage
fi

eval set -- "$params"
unset params

while true
do
    case $1 in
        -d|--diff)
            diff_exec=(${2-})
            shift 2
            ;;
        -e|--exclude)
            # Will override $default_excludes
            excludes+=("${2-}")
            shift 2
            ;;
        -f|--force)
            action='R'
            shift
            ;;
        -s|--skip-existing)
            action='S'
            shift
            ;;
        -h|--help)
            usage
            exit
            ;;
        -v|--verbose)
            verbose='--verbose'
            shift
            ;;
        --)
            shift
            if [ -z "${1:-}" ]
            then
                error "Missing targets." "$help_info" $EX_USAGE
            fi
            if [ -z "${2:-}" ]
            then
                error "Missing directory." "$help_info" $EX_USAGE
            fi
            targets=(${@:1:$(($#-1))})
            source_dir="${@:$#}"
            break
            ;;
        *)
            usage
            ;;
    esac
done
5
  • on the line where I have the if statement, am I managing the sequence of the args properly? I feel like it could become a long if statement if there are like 5 args...
    – nullByteMe
    Commented May 23, 2013 at 13:49
  • @nkon You don't need that if statement. It's a lot simpler if you simply loop through all the arguments and trust getopt to check if there are values where there should be.
    – l0b0
    Commented May 23, 2013 at 14:03
  • What is the -o on the first line with the getopt param list?
    – nullByteMe
    Commented May 23, 2013 at 14:24
  • @nkon Please at least check the man page before asking - It's the option for specifying command options.
    – l0b0
    Commented May 23, 2013 at 14:37
  • 1
    @nkon Sorry, then you're probably using a different version. As in your original code, it should probably work without -o.
    – l0b0
    Commented May 23, 2013 at 14:51

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