So i want to make a "program" that facilitates commands like the yum commands and anothers... when the program is finished i want put it in /usr/bin with the name "dafs"
i tested with this example which the filename is dafs
#!/bin/bash
$1 $2 $3
function yum {
function maintenance {
yum -y update
yum -y upgrade
yum clean all
}
function download {
yum -y install --downloadonly $3
}
}
but when i run ./dafs yum maintenance
or ./dafs yum download http
it don't work i guess because the syntax is incorrect..
So, how can i pass arguments to functions or sub functions, like the example above?
Instead, Bash functions work like shell commands and expect arguments to be passed to them in the same way one might pass an option to a shell command (e.g. ls -l ). In effect, function arguments in Bash are treated as positional parameters ( $1, $2.. $9, ${10}, ${11} , and so on).
To pass any number of arguments to the bash function simply put them right after the function's name, separated by a space. It is a good practice to double-quote the arguments to avoid the misparsing of an argument with spaces in it. The passed parameters are $1 , $2 , $3 …
Arguments can be passed to the script when it is executed, by writing them as a space-delimited list following the script file name.
A best-practice way to define subcommands is with a prefixed namespace, and a "launcher" function. This is how git
does it, for instance (using git-foo
and git-bar
commands for git foo
and git bar
).
Here, I'm using double-underscores rather than a single dash as the separator, as underscores (unlike dashes) are defined as valid within function names by the POSIX sh standard.
yum__maintenance() {
command yum -y update
command yum -y upgrade
command yum clean all
}
yum__download() {
command yum -y install --downloadonly "$@"
}
yum() {
local cmdname=$1; shift
if type "yum__$cmdname" >/dev/null 2>&1; then
"yum__$cmdname" "$@"
else
command yum "$cmdname" "$@" # call the **real** yum command
fi
}
# if the functions above are sourced into an interactive interpreter, the user can
# just call "yum download" or "yum maintenance" with no further code needed.
# if invoked as a script rather than sourced, call function named on argv via the below;
# note that this must be the first operation other than a function definition
# for $_ to successfully distinguish between sourcing and invocation:
[[ $_ != $0 ]] && return
# make sure we actually *did* get passed a valid function name
if declare -f "$1" >/dev/null 2>&1; then
# invoke that function, passing arguments through
"$@" # same as "$1" "$2" "$3" ... for full argument list
else
echo "Function $1 not recognized" >&2
exit 1
fi
Items of note:
"$@"
expands to the full list of arguments passed to the current item in scope, preserving argument boundaries and avoiding glob expansion (unlike $*
and unquoted $@
).shift
pops the first argument ($1
) off the front of the list, leaving the new value of "$@"
one shorter than the old list.command
builtin causes the real yum
command to be called, rather than simply recursing into the yum
function again, when no subcommand exists.declare -f funcname
returns true (and prints that function's definition) if really passed a function. type
, by contrast, returns true if passed any kind of runnable command. Thus, using type "yum__$cmdname"
allows yum__foo
to be defined as an external script or any other type of command, not just a function, whereas the declare -f "$1"
done later allows only functions to be run.A final thing to consider, if you don't intend to support being sourced, would be leaving out the yum
function, but expanding your launcher to recognize subcommands itself:
if declare -f "${1}__$2" >/dev/null; then
func="${1}__$2"
shift; shift # pop $1 and $2 off the argument list
"$func" "$@" # invoke our named function w/ all remaining arguments
elif declare -f "$1" >/dev/null 2>&1; then
"$@"
else
echo "Neither function $1 nor subcommand ${1}__$2 recognized" >&2
exit 1
fi
In this case, a subcommand named by the first two arguments is always searched for, followed by a function named by the first argument only.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With