3

I need to intercept each command I type on the command line, such that I can decorate them.

For example, whenever I type echo Hi what I really want to be executed is /bin/wrapper "echo Hi".

Is there anyway to achieve this in bash, except from recompiling it?

EDIT: Also, for _ in 1 2; do ping -c1 google.com; done must become /bin/wrapper "for _ in 1 2; do ping -c1 google.com; done"

  • 4
    the DEBUG trap may be one way to go. "The trap builtin (see Bourne Shell Builtins) allows a DEBUG pseudo-signal specification, similar to EXIT. Commands specified with a DEBUG trap are executed before every simple command, for command, case command, select command, every arithmetic for command, and before the first command executes in a shell function. The DEBUG trap is not inherited by shell functions unless the function has been given the trace attribute or the functrace option has been enabled using the shopt builtin. The extdebug shell option has additional effects on the DEBUG trap." – Jeff Schaller Jun 6 '17 at 15:42
  • example: unix.stackexchange.com/a/44723/117549 – Jeff Schaller Jun 6 '17 at 15:43
  • 1
    Maybe alias could be a solution: alias echo="echo you typed: ", so echo here we go will result in you typed: here we go. But I am not sure how it will behave overwriting bash build in commands. And it won't repeat your command this way ... – ChristophS Jun 6 '17 at 15:46
2

You can do this with bash-preexec.

Download the script:

wget 'https://raw.githubusercontent.com/rcaloras/bash-preexec/master/bash-preexec.sh'

Source the script:

source 'bash-preexec.sh'

Now, according to its usage notes:

Two functions preexec and precmd can now be defined and they'll be automatically invoked by bash-preexec if they exist.

preexec Executed just after a command has been read and is about to be executed. The string that the user typed is passed as the first argument.

precmd Executed just before each prompt. Equivalent to PROMPT_COMMAND, but more flexible and resilient.

You can use these like so:

preexec() { echo "just typed $1"; }

precmd() { echo "printing the prompt"; }

It might also be worth mentioning that bash-preexec is just a shell script which is implemented using the DEBUG trap and the PROMPT_COMMAND environment variable.

For more information about the DEBUG trap see the reference documentation for the trap command:

For more information about the PROMPT_COMMAND environment variable refer to the Bash manual:

0

This is achievable in Zsh. Zsh is a broadly used shell that uses a language that is pretty much a superset of bash, and designed to have a very customisable UI.

In Zsh, you can define an arbitrary function to to be carried out when you press enter. This can do arbitrary things to the contents of the line. (See the accept-line widget). One solutions is therefore to switch to using Zsh.

  • The question explicitly asks for a bash solution: "Is there anyway to achieve this in bash, except from recompiling it?" – igal Nov 25 '17 at 22:27
  • It does. I think explicit is a bit strong since switching from bash to zsh can be done at very little learning cost, so switching to zsh is a valid solution to the problem. Do you not think it is possible that the person asking this question would be interested to know that this can be achieved by switching to zsh? Do you not think that other people would be interested in this? A question always represents a set of assumptions made by the asker about what the best way to solve their problem is. These assumptions may be flexible. As such a little generalising of the problem can be useful. – Att Righ Nov 25 '17 at 22:57
  • Well, it was definitely stated explicitly. That just means that it was stated directly and unambiguously, as opposed to being communicated implicitly (i.e. being implied). If you want keep your solution posted I would consider adding a sentence to acknowledge that you're not answering the question exactly as asked - just for the sake of clarity. – igal Nov 25 '17 at 23:12
  • Hmm... so the question is what was stated explicitly. – Att Righ Nov 25 '17 at 23:29
  • It sounds like we're miscommunicating, but I'm not sure where. All I'm saying is that the question was specifically about bash. The exact words are: "Is there anyway to achieve this in bash, except from recompiling it?" – igal Nov 25 '17 at 23:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.