I'd like to edit my .bashrc so that every command executed on the shell is piped to something, for example:
$ sudo apt update
_________________
< sudo apt update >
-----------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
I have managed something rather similar, but not entirely:
$ bash
$ exec > >(cowsay)
$ echo "Hello AU!"
$ exit
_______
< Hello AU! >
-------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
It is not the desired result, as it only happens after exiting the current shell.
It's mainly for fun/learning purposes.
Best Answer
You can adapt your method a bit. Instead of piping to
cowsay
directly, read output till a delimiting character, send that output tocowsay
, then print that character after every command:Here, I'm using the ASCII NUL character. You can use something else that's unlikely to appear in command output.
This will print after the prompt, so the output will be ugly:
Note that this will break any command which tries complex output or has a text user interface (think command line editors, pagers, etc.).
Assuming you already know what
exec > >(...)
does, the part in the process substitution is:while IFS= read -d '' -r line; do ... done
: this is a fairly common idiom for reading data delimited by the ASCII NUL character:IFS=
sets the IFS to the empty string, which disables field splitting-r
preventsread
from treating\
in the input specially (so,\n
for example, is read as\n
and not converted to the newline character).-d ''
is the way to tellread
to read until the NUL characterSo the whole thing loops over input in NUL-delimited sections, while preserving the contents of the input as much as possible.
if [[ -n $line ]]; then ... fi; done
- only act if the input read so far is not empty.echo; printf "%s\n" "$line" | cowsay;
- print a leading empty line, so that the cowsay output doesn't clash with the prompt, and then send the input read so far to cowsay.printf
is more reliable and safer thanecho
.