Reputation: 621
I have some lengthy scripts calling each other and I want their output to be more descriptive. The idea is to customize the echo command for each script with something like below.
My question is, how to make it non recursive, using echo
?
this is script1.sh
#!/bin/bash
#Original version:
#function echo(){ echo $(basename $0 .sh): $1; }
#Version after fixes
function echo(){ builtin echo -n "$(basename $0 .sh): ">&2; builtin echo $@ ; }
echo Info
./script2.sh
this is script2.sh
#!/bin/bash
#Original version:
#function echo(){ echo $(basename $0 .sh): $1; }
#Version after fixes
function echo(){ builtin echo -n "$(basename $0 .sh): ">&2; builtin echo $@ ; }
echo Info
exit 0
so the output should be:
>./script1.sh
script1: Info
script2: Info
--- EDIT
Bonus:
>./script1.sh 2> /dev/null
Info
Info
Upvotes: 4
Views: 6714
Reputation: 1212
builtin
only works for shell internal commands like echo
. I know the original question is specifically related to echo
, but as this was a popular Google hit for "bash override function", I thought I'd add my solution for other commands. I'm writing a wrapper to change terminal name when I run ssh
, so I defined a function called ssh
and need to call the actual binary from within. It may not be the best way, but it works to do:
function ssh {
$(which ssh) $@
}
Upvotes: 2
Reputation: 2052
I came up with I/O redirection as a solution. The Bash Redirections Using Exec article inspired me. It has the following implications:
In my bash
shell scripts I use:
alias start_log_ctx="start_filter_by_pipe_regex 2 s/.*/${0##*/}\(pid=$$\): \0/"
function start_filter_by_pipe_regex {
declare -r a="$(mktemp -u)" #1
mknod "$a" p #2
sed <"$a" ">&$1" "$2" & #3
exec "$1">"$a" #4
}
alias stop_log_ctx_by_job="stop_filter_by_pipe_job 2"
def stop_filter_by_pipe_job {
exec "$1">&- #1
wait "$2" #2
}
In essence the start_log_ctx
alias uses sed
to line-wise (.*
) filter the script's I/O that goes to the error output (2
) and prepends the script's base name (${0##*/}
) and process id (pid=$$
) to each line. The start_filter_by_pipe_regex
function works as follows:
-U
) a temporary file.sed
as a filter in the background (&
). Let it read (<
) from the pipe of [2.] and redirect its standard output (>
) to the file descriptor given as the 1. parameter. Pass the filter given as 2. parameter to sed
.>
) the file descriptor given as the 1. parameter to the pipe of [2.].The stop_log_ctx
alias closes the error output's file descriptor (2
) and waits for the previously started sed
to stop. It implicitly does so upon closing the file descriptor. The stop_filter_by_pipe_job
function does the following:
sed
.sed
identified by the bash job given as the 2. parameter to stop.At the beginning of my main function I usually do a declare -r a="$(start_log_ctx)"
and finish with a stop_log_ctx_by_job "$a"
.
Upvotes: 0
Reputation: 27053
use the builtin
keyword:
function echo(){ builtin echo $(basename $0 .sh): $1; }
here the help page:
$ help builtin
builtin: builtin [shell-builtin [arg ...]]
Execute shell builtins.
Execute SHELL-BUILTIN with arguments ARGs without performing command
lookup. This is useful when you wish to reimplement a shell builtin
as a shell function, but need to execute the builtin within the function.
Exit Status:
Returns the exit status of SHELL-BUILTIN, or false if SHELL-BUILTIN is
not a shell builtin..
Upvotes: 15