user391986
user391986

Reputation: 30906

shell script arguments non positional

Is there a way to feed non positional arguments to a shell script? Meaning explicitly specify some kind of flag?

. myscript.sh value1 value2
. myscript.sh -val1=value1 -val2=value2

Upvotes: 4

Views: 4403

Answers (5)

ti regist
ti regist

Reputation: 14

Script has arguments as follows: - $0 - script name - $1, $2, $3.... - received arguments $* = all arguments, $# = number of arguments

Reference: http://famulatus.com/ks/os/solaris/item/203-arguments-in-sh-scripts.html

Upvotes: 0

Richard Hansen
Richard Hansen

Reputation: 54223

You can use getopts, but I don't like it because it's complicated to use and it doesn't support long option names (not the POSIX version anyway).

I recommend against using environment variables. There's just too much risk of name collision. For example, if your script reacts differently depending on the value of the ARCH environment variable, and it executes another script that (unbeknownst to you) also reacts to the ARCH environment variable, then you probably have a hard-to-find bug that only shows up occasionally.

This is the pattern I use:

#!/bin/sh

usage() {
    cat <<EOF
Usage: $0 [options] [--] [file...]

Arguments:

  -h, --help
    Display this usage message and exit.

  -f <val>, --foo <val>, --foo=<val>
    Documentation goes here.

  -b <val>, --bar <val>, --bar=<val>
    Documentation goes here.

  --
    Treat the remaining arguments as file names.  Useful if the first
    file name might begin with '-'.

  file...
    Optional list of file names.  If the first file name in the list
    begins with '-', it will be treated as an option unless it comes
    after the '--' option.
EOF
}

# handy logging and error handling functions
log() { printf '%s\n' "$*"; }
error() { log "ERROR: $*" >&2; }
fatal() { error "$*"; exit 1; }
usage_fatal() { error "$*"; usage >&2; exit 1; }

# parse options
foo="foo default value goes here"
bar="bar default value goes here"
while [ "$#" -gt 0 ]; do
    arg=$1
    case $1 in
        # convert "--opt=the value" to --opt "the value".
        # the quotes around the equals sign is to work around a
        # bug in emacs' syntax parsing
        --*'='*) shift; set -- "${arg%%=*}" "${arg#*=}" "$@"; continue;;
        -f|--foo) shift; foo=$1;;
        -b|--bar) shift; bar=$1;;
        -h|--help) usage; exit 0;;
        --) shift; break;;
        -*) usage_fatal "unknown option: '$1'";;
        *) break;; # reached the list of file names
    esac
    shift || usage_fatal "option '${arg}' requires a value"
done
# arguments are now the file names

Upvotes: 5

clt60
clt60

Reputation: 63952

Example:

#!/bin/bash
while getopts d:x arg
do
        case "$arg" in
                d) darg="$OPTARG";;
                x) xflag=1;;
                ?) echo >&2 "Usage: $0 [-x] [-d darg] files ..."; exit 1;;
        esac
done
shift $(( $OPTIND-1 ))

for file
do
        echo =$file=
done

Upvotes: 2

William Pursell
William Pursell

Reputation: 212454

The easiest thing to do is pass them as environment variables:

$ val1=value1 val2=value2 ./myscript.sh

This doesn't work with csh variants, but you can use env if you are using such a shell.

Upvotes: 4

bpgergo
bpgergo

Reputation: 16037

Yes there is. The name is getopts http://www.mkssoftware.com/docs/man1/getopts.1.asp

Upvotes: 2

Related Questions