Reputation: 30906
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
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
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
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
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
Reputation: 16037
Yes there is. The name is getopts http://www.mkssoftware.com/docs/man1/getopts.1.asp
Upvotes: 2