2

Is there someway to alter the Bash system error message template so that you can print something in addition to the original message? For example:

Macbook Air:~/Public]$ lfe
-bash: lfe: WTF command not found

or

Macbook Air:~/Public]$ lfe
-bash: lfe: #!&**! command not found
Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
pmagunia
  • 1,718
  • 1
  • 22
  • 33
  • 1
    Depends on your setup. For me (Ubuntu 16.04), there is a Python script at `/usr/lib/command-not-found` that prints the message that you could edit. It is called from a function declared in `/etc/bash.bashrc`, and that is sourced in `/etc/profile`. – Benjamin W. Mar 17 '17 at 19:22
  • You can check where the function is for you if you turn on `set -x` and issue a non-existing command. – Benjamin W. Mar 17 '17 at 19:24
  • Is there a way to 'undo' the `set -x` command? It'd be nice to add a message for other types of error messages too. – pmagunia Mar 17 '17 at 20:30
  • The set command prints the last command to the console I think. – pmagunia Mar 17 '17 at 20:37
  • Undo set: `set +x` – Benjamin W. Mar 17 '17 at 21:07
  • I just realize that `command_not_found_handle` was introduced in Bash 4.0, so you won't have it on a Mac. – Benjamin W. Mar 17 '17 at 21:08

2 Answers2

4

Since Bash 4.0, if the search for a command is unsuccessful, the shell searches for a function called command_not_found_handle. If it doesn't exist, Bash prints a message like this and exits with status 127:

$ foo
-bash: foo: command not found
$ echo $?
127

If it does exist, it is called with the command and its arguments as arguments, so if you have something like

command_not_found_handle () {
    echo "It's my handle!"
    echo "Arguments: $@"
}

in your .bashrc, Bash will react like this:

$ foo bar
It's my handle!
Arguments: foo bar

Most systems have something much more sophisticated in place, though. My Ubuntu, for example, has this in /etc/bash.bashrc:

# if the command-not-found package is installed, use it
if [ -x /usr/lib/command-not-found -o -x /usr/share/command-not-found/command-not-found ]; then
    function command_not_found_handle {
            # check because c-n-f could've been removed in the meantime
                if [ -x /usr/lib/command-not-found ]; then
           /usr/lib/command-not-found -- "$1"
                   return $?
                elif [ -x /usr/share/command-not-found/command-not-found ]; then
           /usr/share/command-not-found/command-not-found -- "$1"
                   return $?
        else
           printf "%s: command not found\n" "$1" >&2
           return 127
        fi
    }
fi

and this is sourced from /etc/profile. /usr/lib/command-not-found is a Python script that uses some more Python (CommandNotFound) to basically look up packages that are named like the unknown command, or sound similar:

$ sl
The program 'sl' is currently not installed. You can install it by typing:
sudo apt install sl
$ sedd
No command 'sedd' found, did you mean:
 Command 'sed' from package 'sed' (main)
 Command 'seedd' from package 'bit-babbler' (universe)
 Command 'send' from package 'nmh' (universe)
 Command 'send' from package 'mailutils-mh' (universe)
sedd: command not found

So if you want simple customization, you can provide your own command_not_found_handle, and if you want to customize the existing system, you can modify the Python scripts.

But, as mentioned, this requires Bash 4.0 or higher.

Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
2

Maybe something like:

curl https://raw.githubusercontent.com/rcaloras/bash-preexec/master/bash-preexec.sh -o ~/.bash-preexec.sh
echo '[[ -f ~/.bash-preexec.sh ]] && source ~/.bash-preexec.sh' >> ~/.bashrc

then add the following to .bashrc too

preexec() { type "$1" >/dev/null 2>&1 || echo -n 'WTF??? '; }

reload your shell, then try enter some nonexistent command, like bububu

$ bububu

will print

WTF??? -bash: bububu: command not found

Important: read https://github.com/rcaloras/bash-preexec

clt60
  • 62,119
  • 17
  • 107
  • 194