Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm trying to write bash command wrapper, which will be patch bash current command on the fly. But i'm faced with the problem. As i'm not a good Shell user, i can't write right expression of variable assignment in string. See bellow:

I'm set trap to preexecute, through this:

 alex@bender:~$ trap "caller >/dev/null ||  xxx \"\${BASH_COMMAND}"\"  DEBUG;

I want change variable BASH_COMMAND, do something like BASH_COMMAND=xxx ${BASH_COMMAND} but i don't know, how i need escaping variables in this string

NOTE: xxx -- my custom function, which must return some value, if in end of command situated word teststr

function xxx(){
# find by grep, if teststr in the end
`echo "$1" | grep "teststr$" >/dev/null`;
# if true ==> do
if [ "$?" == "0" ]; then
    # cut last 6 chars (len('teststr')==6)
    var=`echo "$1" | sed 's/......$//'`;
    echo "$var";
fi    }

How can i do this stuff?:

alex@bender:~$ trap "caller >/dev/null || ${BASH_COMMAND}=`xxx $BASH_COMMAND`"  DEBUG;
share|improve this question
I don't believe it is possible to change bash input in this way. You might be able to do it with a readline hook, though. It would be useful to know what exactly you wish to accomplish because there might well be another way to do so. – rici Oct 27 '13 at 19:50
up vote 2 down vote accepted

Here is a possible solution, but it will trap all commands, not only those entered through the prompt (so commands in scripts will be trapped too). You may have to modify it to get what you want.

First, set shopt extdebug option.

From the manual:

If set, behavior intended for use by debuggers is enabled:

1- The -F option to the declare builtin (see Bash Builtins) displays the source file name and line number corresponding to each function name supplied as an argument.
2- If the command run by the DEBUG trap returns a non-zero value, the next command is skipped and not executed.
3- If the command run by the DEBUG trap returns a value of 2, and the shell is executing in a subroutine (a shell function or a shell script executed by the . or source builtins), a call to return is simulated.
4- BASH_ARGC and BASH_ARGV are updated as described in their descriptions (see Bash Variables).
5- Function tracing is enabled: command substitution, shell functions, and subshells invoked with ( command ) inherit the DEBUG and RETURN traps.
6- Error tracing is enabled: command substitution, shell functions, and subshells invoked with ( command ) inherit the ERR trap.

(emphasis mine)

You need this command to cancel the execution of the command entered by the user and call your custom function instead. If this is not set, Bash will call your custom function and execute the user’s command.

Then, use simple quotes to write your trap to prevent Bash variable expansion:

trap 'caller >/dev/null || xxx $BASH_COMMAND' DEBUG

Now, if your xxx function returns a non-zero value (e.g. 1), the user’s command will not be executed.

Here is a full example:

$ shopt -s extdebug
$ xxx() { if [ "$1" = 'sudo' ]; then echo "No sudo, please.";return 1; fi }
$ trap 'caller >/dev/null || xxx $BASH_COMMAND' DEBUG
$ ls
foo bar
$ sudo ls
No sudo, please.

In this example, xxx check if the first word of the command is sudo, and if so prints a message and cancel the command. You can get the whole user command in xxx by using "$*".

share|improve this answer
Thanks, @bfontaine. It will very useful for me. – Alex_Bender Oct 28 '13 at 10:31

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .