Reputation: 105
I have a shell script (say test.sh
) which calls more shell scripts (not written by me). These other shell scripts (say test2.sh
and test3.sh
) are complicated which I do not want to edit (for reasons of not messing as well as keeping the option of update alive)
test2.sh
and test3.sh
has several calls to various shell builtins (eg echo
). I want to change the definition of (example) echo
in test.sh so that whenever test2.sh
is called, I get a modified echo
of the type
echo [test2] blah blah
Then before invoking test3.sh
I want to alter echo
once again so that all the echo
's of test3.sh
work as-
echo [test3] blah blah
I have tried doing that with alias
, export
, function
etc. none of which works as desired. I am including my examples below -
file :: test.sh
#!/bin/bash
#alias echo='function __echo(){ /bin/echo [DB] $* ; unset -f __echo;}; __echo ' # does not work
echo() { /bin/echo [test2] $* ; }; # works only within test.sh. test2.sh does not see this function. exporting does not help.
echo "blah" "blah"; # echoes [test2] blah blah
./test2.sh "one more arg" "second arg";
echo() { /bin/echo [test3] $* ; }; # no luck once again
./test3.sh "test3 arg1" "test3 arg2";
file :: test2.sh
#!/bin/bash
/bin/echo "First arg = \"$1\""; # no problem here
/bin/echo "Secnd arg = \"$2\"";
echo $1 # behaves as the usual echo
echo $2
echo $*
Any ideas how to do it? If possible not just for echo
but for other utilities too.
Upvotes: 0
Views: 61
Reputation: 105
Though @ruakh's suggested modification of my original approach works well, it messes with other things. If test2.sh
or test3.sh
have redirected echo
s then none of those redirected echo
s will work properly. I want only those lines directed to stdout
to be affected.
Since then I have found a new solution, which admittedly is somewhat cumbersome.
file :: test.sh
#!/bin/bash
echo "blah blah"; # no change here
y=`./test2.sh "arg 1" "arg 2" 2>/dev/null`
while read -r x
do
echo "[test2] $x";
done <<< "$y"; # correctly appends [test2] before every output of test2.sh
#similarly for `test3.sh`
now even if test2.sh
contains line of the form
echo "some text" > file1;
only those lines actually coming out to stdout will be affected.
But now every invocation of test2.sh
must be changed :(
Upvotes: 0
Reputation: 183436
You had it right with export
, but since shell functions aren't just normal variables, you need to use the special -f
flag:
export -f echo
I think the implementation details depend on the version of Bash, but on the one I have handy, export -f
works by creating an environment variable named BASH_FUNC_the_function_name()
and setting it to () { the_function_body ; }
. When Bash starts up, it searches for environment variables of that form, and creates the appropriate functions. (A quirk in this functionality is what enabled the Shellshock security vulnerability.)
Upvotes: 1