81

I want to write a bash script which takes different arguments. It should be used like normal linux console programs:

my_bash_script -p 2 -l 5 -t 20

So the value 2 should be saved in a variable called pages and the parameter l should be saved in a variable called length and the value 20 should be saved in a variable time.

What is the best way to do this?

jww
  • 97,681
  • 90
  • 411
  • 885
Pascal
  • 2,175
  • 4
  • 39
  • 57
  • A variable in what? Parameters are related to the program you're runnning, not bash in this case. Does 'myProgramm' take parameters? – Joe Aug 20 '12 at 11:01
  • I want to write a program in bash which does this. – Pascal Aug 20 '12 at 11:05
  • Note that unless you call the script using '.' (`. myProgram -p2 -l 5 -t 20`), the variables you set will only exist in `myProgram`, not the shell from which you call it. – chepner Aug 20 '12 at 12:51
  • It really seems to me that his intention is that myProgramm is a bash script. In which case getopts is correct. To avoid this confusion maybe myProgramm should be called my_bash_script. Hey what the heck I'll edit it – Captain Lepton Oct 22 '14 at 16:53

2 Answers2

128

Use the getopts builtin:
here's a tutorial

pages=  length=  time=

while getopts p:l:t: opt; do
  case $opt in
  p)
      pages=$OPTARG
      ;;
  l)
      length=$OPTARG
      ;;
  t)
      time=$OPTARG
      ;;
  esac
done

shift $((OPTIND - 1))

shift $((OPTIND - 1)) shifts the command line parameters so that you can access possible arguments to your script, i.e. $1, $2, ...

codeforester
  • 39,467
  • 16
  • 112
  • 140
tzelleke
  • 15,023
  • 5
  • 33
  • 49
  • http://mywiki.wooledge.org/BashFAQ/035 "getopt cannot handle empty arguments strings, or arguments with embedded whitespace. Please forget that it ever existed." – Federico Aug 27 '13 at 16:44
  • 9
    @Federico your confusing `getopt` and `getopts`... you should read your citation carefully (and please retract the down vote). You can also read [here](http://blog.onetechnical.com/2012/07/16/bash-getopt-versus-getopts/) – tzelleke Aug 27 '13 at 21:33
13

Something along the lines of

pages=
length=
time=

while test $# -gt 0
do
    case $1 in
        -p)
            pages=$2
            shift
            ;;
        -l)
            length=$2
            shift
            ;;
        -t)
            time=$2
            shift
            ;;
        *)
            echo >&2 "Invalid argument: $1"
            ;;
    esac
    shift
done
Jo So
  • 25,005
  • 6
  • 42
  • 59
  • 1
    -1, far better to use getopts – Steven Mackenzie Mar 20 '14 at 18:17
  • 2
    @StevenMackenzie, ...I'm not sure I can agree. If you look at [BashFAQ #35](http://mywiki.wooledge.org/BashFAQ/035), the manual-parsing example (of which this is further simplification) does rather a number of things that getopts simply *can't*. Following the practice is thus more flexible. – Charles Duffy Feb 18 '17 at 04:53
  • 2
    @StevenMackenzie, ...we're also in a world where folks have been spoiled by GNUisms such as being able to mix optional and positional arguments (barring the use of `--` to explicitly signal end of the former and beginning of the latter alone). It's easy to do something like `args+=( "$1" )` in a default case with a parser of this kind; with getopts, the cutoff at `OPTIND` is hard-and-fast. – Charles Duffy Feb 18 '17 at 04:58
  • Bash FAQ 35 (as above) tells me everything I need to know – Brian Agnew Aug 14 '18 at 11:04