next::method in bash scripts
In Pre-commit hooks and breaking the build, I wrote a little wrapper around 'svn' to ensure that I could locally alter how it functions. However, I hard-coded the name to the actual executable. I should actually be doing the equivalent of $self->next::method to find the next executable in my path. So I wrote the following bash function to give this a try.
function next() {
curr_exec=$1
shift
if [ -z $curr_exec ]; then
echo "next_exec()" requires an argument
exit 1
fi
if ! type $curr_exec >/dev/null 2>&1; then
echo "next_exec()" argument must be an executable
exit 2
fi
curr_path=$(echo $curr_exec | sed 's|/\w*$||')
executable=$(basename $curr_exec)
found=0
for path in `echo $PATH | sed 's/:/\n/g'`; do
if [ "$path" = "$curr_path" ]; then
found=1
elif [ $found -eq 1 ]; then
if [ -x "${path}/$executable" ]; then
next_exec="${path}/$executable"
break
fi
fi
done
if [ -z $next_exec ]; then
echo Could not find a next_exec for $curr_exec
exit 3
else
$next_exec "$@"
fi
}
This needs some work, but basically, it figures out your path and your executable name. Then it searches through the path to find the next executable with that name. This, I think, makes it safer to write override scripts for various executables and redispatch to them.
So with my svn wrapper, I can call my wrapper or call the thing it wraps.
svn diff
next svn diff
next seems like an awfully common word, though. Will this break anything?
A simpler solution is to write your wrapper as a function, and use 'command svn ARGS' to run svn. 'command' ignores shell functions when searching for the program to run. I use it to wrap rdesktop:
This approach is limited: it's probably bash-specific, and you can't put the function into a stand-alone wrapper unless you change the name - if your stand-alone wrapper is named svn, then 'command svn' will find it first in $PATH.
@John: I edited your response slightly. I indented the code four spaces. Because comments now default to markdown, indenting code four spaces lets you format it nicely.
And thanks for the response.
You’re trying to write sh like you’d write Perl or some other language at that level. That does not make for very idiomatic sh. Also, you’re sticking to generic primitives instead of using the sh “library”, akin to a Perl programmer who doesn’t use any modules.
I’d write it something like this:
And it would be called as