LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   What do you use to support command-line arguments for BASH scripts? (https://www.linuxquestions.org/questions/programming-9/what-do-you-use-to-support-command-line-arguments-for-bash-scripts-4175632854/)

dugan 06-28-2018 11:56 AM

What do you use to support command-line arguments for BASH scripts?
 
What do you use to support command-line arguments in BASH scripts?

I have a script I want to add command-line arguments to. The platforms I need it to run on are Linux and OS X.

The script-in-progress is currently here:

https://gist.github.com/duganchen/7d...311e814d090ab4

I did google, but the results were honestly kind of overwhelming.

I did find ArgBash, but honestly, I'm currently leaning towards getopts.

What does this forum recommend?

Richard Cranium 06-28-2018 12:00 PM

I use getopts.

Gah! That's what I get from posting at work.

I use getopt, which is a GNU beast.
Code:

info getopt
will provide some details.

bassmadrigal 06-28-2018 12:07 PM

I used getopts with a case statement.

https://github.com/bassmadrigal/scri...aster/sbgen.sh

Code:

while getopts "hfw:d:m:D:M:r:" OPTION
do
  case $OPTION in
    h ) help; exit
        ;;
    f ) FORCE=yes
        ;;
    w ) HOMEPAGE=$OPTARG
        ;;
    d ) DOWNLOAD=$OPTARG
        ;;
    m ) MD5SUM=$OPTARG
        ;;
    D ) DOWNLOAD64=$OPTARG
        ;;
    M ) MD5SUM64=$OPTARG
        ;;
    r ) REQUIRES=$OPTARG
        ;;
    * ) help; exit
        ;;
  esac
done
shift $(($OPTIND - 1))


jlinkels 06-28-2018 12:28 PM

I am very happy with shflags. https://github.com/kward/shflags

I think internally it uses getopts as well, but eventually you don't have to do any parsing, and just check or use the parameters as entered.

jlinkels

GazL 06-28-2018 12:29 PM

I never got on with getopts: it doesn't handle gnu style long-options, nor options with optional arguments, and from what I've read its use can also differ between implementations.

I usually just code the option parsing manually, no surprises that way.

orbea 06-28-2018 12:33 PM

Here is a simple portable example.

Code:

help='some help and documentation
  can go here'

while [ $# -gt 0 ]; do
  option="$1"; shift
  case "$option" in
    -- ) break ;;
    -f|--foo ) echo 'foo' ;;
    -b|--bar ) echo 'bar' ;;
    -h|--help ) echo "$help"; exit 0 ;;
    * ) echo "Unrecognized option '$option', use -h for help."; exit 1 ;;
  esac
done


ondoho 06-29-2018 08:02 AM

Quote:

Originally Posted by GazL (Post 5873089)
I never got on with getopts: it doesn't handle gnu style long-options, nor options with optional arguments, and from what I've read its use can also differ between implementations.

I usually just code the option parsing manually, no surprises that way.

coding the option parsing with case-esac and builtin getopts is hardly shorter than coding it completely manually, and does not seem to have any benefits.
nevertheless i've always been using it, just because it's built into bash.
i should try getopt some day.

GazL 06-29-2018 09:47 AM

Even when allowing for POSIX utility syntax conventions such as option combining it's really not hard to code manually, and as you say, it's not that much more long-winded or complex than the case statements employed by getopt(s).

Here's an example I wrote a few years back that follows -- to the best of my understanding -- all the POSIX guidelines, while also including support for GNU long-options. Not including the help, there are 3 example options (each in both long and short form): one with a mandatory argument, one with an optional argument and one without any argument (a basic flag). It uses no external utilities and no bashisms, just basic shell features.

Code:

#!/bin/sh

# Example of parsing command-line options/arguments.

########################################################################
usage()
{
  bs=$(tput bold) ; be=$(tput sgr0)
  cat <<-EOF

        ${bs}SYNOPSIS${be}

            options_sh [-v] [-f option_argument] [-l[option_argument]]
                [--] [operand...]
            options_sh [-?|--help]

        ${bs}DESCRIPTION${be}

            -?
            --help
                Show this usage information and exit.

            -v | --verbose
                Basic flag style option: takes no arguments.

            -f <argument>
            --file=<argument>
                Option that requires an argument.

            -l[n]
            --log[=n]
                Option that takes an optional argument (default: n=1 ).

        EOF
}

########################################################################
# Parse Option Args:

od_log="1"  # Option argument default for "LOG".

unset o_file o_log o_verbose
while [ $# -gt 0 ]
do
  case "$1" in
    --)          shift ; break ;;
    -|""|[!-]*)  break ;;
    -\?|--help)  usage ; exit 0 ;;
    --file=*)    o_file="${1#*=}" ;;
    --log)        o_log="$od_log" ;;
    --log=*)      o_log="${1#*=}" ;;
    --verbose)    o_verbose=1 ;;
    --*)          echo "unknown long option: $1" >&2 ;;
    -?*)          # short options:
                  opts="${1#-}"
                  while [ "${opts}" ]
                  do
                    nopts=${opts#?}
                    opt=${opts%${nopts}}
                    case "${opt}" in
                      v)  o_verbose=1 ;;
                      f)  if [ "${nopts}" ]; then
                            o_file="${nopts}"
                            nopts=""
                          else
                            o_file="${2:?'-f' option expects filename argument!}"
                            shift
                          fi
                          ;;
                      l)  if [ "${nopts}" ]; then
                            o_log="${nopts}"
                            nopts=""
                          else
                            o_log="${od_log}"
                          fi
                          ;;
                      ?)  echo "Invalid option: ${opt}" >&2 ; exit 1 ;;
                    esac
                    opts=${nopts}
                  done
                  ;;
  esac
  shift
done

########################################################################
# Validate input options/arguments:

  # Validate your input here. I find it best to keep parsing and
  # validation as two separate activities, otherwise the code
  # tends to get unwieldy.

########################################################################
# Rest of script:

[ "$o_verbose" ]  &&  echo "VERBOSE Selected"
[ "$o_file" ]    &&  echo "file: $o_file"
[ "$o_log" ]      &&  echo "LOG Selected, Value is: $o_log"


while [ $# -gt 0 ]
do
  echo "Operand: $1"
  shift
done

################################################################# End. #

Anyway, fwiw, that's my basic options boilerplate.

wpeckham 06-29-2018 09:52 AM

Quote:

Originally Posted by dugan (Post 5873064)
What do you use to support command-line arguments in BASH scripts?

I have a script I want to add command-line arguments to. The platforms I need it to run on are Linux and OS X.

The script-in-progress is currently here:

https://gist.github.com/duganchen/7d...311e814d090ab4

I did google, but the results were honestly kind of overwhelming.

I did find ArgBash, but honestly, I'm currently leaning towards getopts.

What does this forum recommend?

Did you examine the BASH man page sections on command line arguments? Everything you really need is there.

dugan 06-29-2018 10:03 PM

Thanks all. I went with getopts.

The finished script is here:

https://github.com/duganchen/md_preview


All times are GMT -5. The time now is 05:24 PM.