How do you write a function in bash that executes the command that it is given as an argument, where
In other words, how to write an as-transparent-as-possible wrapper function.
The goal of the wrapper function could for example be to set the current directory before and after the given command, and/or set environment variables, or time how long the given command takes,... As a simple example here I take a function that just prints a line and then executes the given command.
A first attempt:
function wrap1 {
echo Starting: "$@"
"$@"
}
You could use it like wrap1 echo hello
. But the problem is you cannot do alias myalias echo
and then call wrap1 myalias hello
: it wouldn't resolve the alias.
Another attempt using eval
:
function wrap2 {
echo Starting: "$@"
eval "$@"
}
Now calling an alias works. But the problem is it evaluates the arguments too. For example wrap2 echo "\\a"
prints just a
instead of \a
because the arguments are evaluated twice.
shopt -s expand_aliases
doesn't seem to help here either.
Is there a way to both evaluate aliases like wrap2, but still pass on the arguments directly like wrap1?
To invoke a bash function, simply use the function name. Commands between the curly braces are executed whenever the function is called in the shell script. The function definition must be placed before any calls to the function.
bash [filename] runs the commands saved in a file. $@ refers to all of a shell script's command-line arguments. $1 , $2 , etc., refer to the first command-line argument, the second command-line argument, etc. Place variables in quotes if the values might have spaces in them.
It seems to be possible with a double eval
:
eval "eval x=($(alias y | cut -s -d '=' -f 2))"
# now the array x contains the split expansion of alias y
"${x[@]}" "${other_args[@]}"
So maybe your function could be written as follows:
wrap() {
eval "eval prefix=($(alias $1 | cut -s -d '=' -f 2))"
shift
"${prefix[@]}" "$@"
}
However, eval
is evil, and double eval
is double evil, and aliases are not expanded in scripts for a reason.
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