How to replace cat with bat system-wide Ubuntu 22.04
I would recommend strongly against that.
Cat is not just for interactive use on the shell; it is also used in system scripts as cat <file> | filter | ...
, or DATA="$(cat <file>)"
.
If Bat doesn't behave exactly the same in these situations, your system may end up breaking in unexpected ways, and you may not even think to connect these breakages to your replacement of Cat.
(an example I found is bat /dev/zero | head -c1
that exhausts all system memory and then crashes, where cat
works just fine; see issue #636)
I am using Ubuntu 22.04 with bash, pretty vanilla, and have added alias cat="batcat" to ~/.bashrc.
That's less harmful; it only affects your interactive use of the shell; not scripts, and not other (system) users.
Still, I would also recommend against that.
Again, if Bat does not behave exactly as Cat, it may break still break your shell somewhat, for example if you copy/paste a command line that uses cat
from somewhere.
For an example, see bat issue #2380, where someone complains that zsh-async
breaks after doing alias cat=bat
.
However, when I run a command such as crontab -l
, the output appears to be using cat instead of batcat.
Just because something produces output, doesn't mean it uses Cat.
crontab -l
just prints its output. It's not fed through Cat, or even the system pager (see below). You'll have to use | batcat
manually.
(that said, with the Bat version I have on my system, crontab -l | batcat
does not colorize anything, so I'm not sure there's much value to be had here)
So, what can you do?
Well, first of all, you can simply use batcat <file>
or <command> | batcat
when you want the colorized output.
This makes the usage more explicit, so it won't mess up anything it's not supposed to.
You're free to define another alias using alias XXX="batcat"
, so you can use it with less typing in interactive shell sessions. I recommend against aliasing over Cat, but bat
or bc
seem fine aliases to me.
In shells such as Zsh, you could consider a global alias to save even more typing and reduce the command to something like crontab -l B
. But be careful, global aliases are their own can of worms.
Another idea is creating an alias that reruns the previous command, and pipes its output through Bat; for example: alias rebat='$(history -p !!) | batcat'
.
Then, if you run crontab -l
and decide you would've rather piped its output through Bat, you can simply type rebat
, and that will run crontab -l | batcat
for you.
Pagers
Unix has the concept of a pager; a program that can display text a page at a time and allows you to navigate through the text. The most ubiquitous pager is probably Less. Some programs (man, git, systemctl, etc) automatically send their output through a pager.
You could set Bat as the default pager using export PAGER=bat
(e.g. in your .bashrc
), that would make those programs use Bat by default.
Note that the pager MUST be called bat
, not batcat
. Bat only colorizes output, it does not offer pagination. If Bat sees that its output is too long for the terminal, it will automatically feed its output through $PAGER
.
However, since $PAGER=bat
, it will start a new Bat, and feed its output there. That new Bat sees the output is too long, so it will start a pager, which is yet another Bat. This repeats indefinitely (see issue 2023).
To prevent this, Bat detects if the pager is set to Bat and quietly uses Less instead for pagination. But this only works if the pager is set to bat
, not batcat
.
To achieve that, you could symlink batcat
to bat
somewhere. $HOME/bin
would be my preference, but you need to have your shell set up to use that. /usr/local/bin
would be a system-wide option.