Wednesday, May 15, 2024
31
rated 0 times [  31] [ 0]  / answers: 1 / hits: 3455  / 2 Years ago, tue, august 23, 2022, 1:34:49

I am using Ubuntu 22.04 with bash, pretty vanilla, and have added alias cat="batcat" to ~/.bashrc. The program batcat or bat being referred to can be found here: https://github.com/sharkdp/bat


So, when I run cat ~/.bashrc, for instance, it outputs the contents of the file using batcat. However, when I run a command such as crontab -l, the output appears to be using cat instead of batcat.


Any help would be highly appreciated!


It appears that crontab -l is not using cat, due to the output of strace crontab -l |& grep cat. Does that mean there's nothing I can do?


It is still possible to grab the output and feed it into crontab, using crontab -l | batcat or crontab -l | cat.


More From » command-line

 Answers
1

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.


[#120] Wednesday, August 24, 2022, 2 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
memorrappin

Total Points: 325
Total Questions: 122
Total Answers: 100

Location: Armenia
Member since Sat, Sep 12, 2020
4 Years ago
memorrappin questions
Fri, Aug 12, 22, 14:45, 2 Years ago
Thu, Jan 12, 23, 01:52, 1 Year ago
Fri, Sep 9, 22, 05:27, 2 Years ago
Sun, Apr 3, 22, 16:14, 2 Years ago
;