cat does exactly one thing: it prints a file to the terminal. That is its virtue and the reason it is in every pipeline you have ever written. It is also why reading a 400-line config file with cat means watching it scroll past and then reaching for less instead.
bat is cat with syntax highlighting, line numbers, git change markers, and a pager that appears automatically when the file is long. For reading, it is a straightforward improvement. For everything else, it is the wrong tool, and knowing where that line falls is most of what this page is about.
The short verdict
Use bat when a human is reading the file. Config files, scripts, source code — highlighting genuinely helps you spot the block you are looking for, and the line numbers save you counting.
Use cat in pipes and scripts, always. Not as a fallback — as the correct choice. Piping bat into another command is asking for trouble you do not need.
Keep less for large files and for searching inside one. bat uses less as its pager anyway.
Installing it, and the naming trap
sudo apt install bat # Debian, Ubuntu
sudo dnf install bat # Fedora, RHEL, Rocky, Alma
sudo pacman -S bat # Arch
brew install bat # macOSOn Debian and Ubuntu the command is batcat, not bat. The name bat belonged to an unrelated package first, so Debian renamed the binary — exactly as it did for fd, which becomes fdfind. Every guide will say bat and your shell will say “command not found”.
# Confirm what you got
which batcat
# Symlink it so tutorials work
mkdir -p ~/.local/bin
ln -s $(which batcat) ~/.local/bin/batPrefer the symlink to an alias, for the same reason as with fd: aliases exist only in interactive shells, so scripts, xargs and sudo will not see one. fd vs find covers the same trap.
What bat adds
| cat | less | bat | |
|---|---|---|---|
| Syntax highlighting | No | No | Yes |
| Line numbers | cat -n | less -N | Yes, by default |
| Pages long files automatically | No | Yes | Yes |
| Shows git modifications | No | No | Yes |
| Shows non-printing characters | cat -A | Partially | -A |
| Concatenates files | Yes | No | Yes |
| Safe in a pipe | Yes | n/a | Needs care |
| Installed everywhere | Yes | Yes | No |
The git column is the quietly useful one. Open a file inside a repository and bat marks changed lines in the gutter, so you can see what you have edited without switching to git diff.
# Read a file
bat /etc/nginx/nginx.conf
# Just a range of lines
bat -r 40:60 /etc/ssh/sshd_config
# No line numbers or decoration - closer to cat
bat -p file.txt
# Force a language when the extension does not say
bat -l ini myconfig
# Show tabs, spaces and line endings
bat -A file.txt
# What languages and themes does it know?
bat --list-languages
bat --list-themesbat -r 40:60 is worth committing to memory. When a config test tells you the error is on line 47, that prints the neighbourhood with highlighting rather than making you page there. bat -A is the other one — it makes trailing whitespace and tab-versus-space problems visible, which is a whole class of “but it looks identical” bug.
Using bat as a pager for other tools
This is where bat earns its place beyond just reading files. Several tools will happily hand their output to it.
# Syntax-highlighted man pages
export MANPAGER="sh -c 'col -bx | bat -l man -p'"
# Highlighted git diffs
git config --global core.pager "bat -p"
# Highlighted help output
help() { "$@" --help 2>&1 | bat -pl help; }The MANPAGER line is the best of the three. Man pages are dense walls of monospace, and colour makes the flag definitions genuinely easier to scan. Put it in ~/.bashrc. tldr vs man covers the other half of making documentation readable.
For git diffs specifically, delta is purpose-built and better than bat — it understands diff structure rather than just colouring the text.
Where cat is still the right answer
Stronger than usual here, because bat in the wrong place actively breaks things.
- Anything in a pipe. bat detects when it is not writing to a terminal and drops its decoration, so it mostly behaves — but “mostly” is not a property you want in a script.
catpasses bytes through unchanged, always, and that predictability is the entire point. - Scripts. Same reason, plus bat may not be installed on the machine the script runs on.
- Binary or unknown files. bat is built for source and config;
catandxxdare what you want for anything else. - Machines you do not control. The usual reason, and the reason the
cathabit is worth keeping. - Genuinely concatenating files — the job cat is actually named after:
cat part1 part2 > whole.
And a word for less, which neither tool replaces. On a multi-gigabyte log, less opens instantly because it only reads what it displays. Inside it, / searches, n jumps to the next match, G goes to the end and F follows a growing file like tail -f — but lets you stop and scroll back. That last trick alone is worth knowing.
The rule for this section holds: learn cat and less, install bat. Read with bat; pipe with cat; open big files with less.
Configuration
# ~/.config/bat/config
--theme="Dracula"
--style="numbers,changes,header"
--italic-text=alwaysThe --style option controls how much decoration you get. numbers,changes,header is a good middle ground; --style=plain gives you highlighting and nothing else, which is what you want when copying text out of the terminal, since the line numbers otherwise come with it.
If your theme looks wrong, it is nearly always the terminal rather than bat — bat --list-themes shows previews, and there are separate light and dark defaults.
Quick reference
| You want | Command |
|---|---|
| Read a file properly | bat file |
| Only lines 40–60 | bat -r 40:60 file |
| No decoration, for copying | bat -p file |
| Reveal tabs and trailing spaces | bat -A file |
| Force a syntax | bat -l yaml file |
| Coloured man pages | Set MANPAGER, see above |
| Feed a pipeline | cat file | ... |
| Open a huge log | less file, then / to search |
| Follow a growing file, scrollably | less +F file |
| Debian: it is called | batcat |
Related reading
- fd vs find — the same Debian renaming trap
- tldr vs man — the other half of readable documentation
- ripgrep vs grep — finding the file before you read it
- Terminal editors — when reading is not enough
- Reading Linux logs — where
lessearns its keep - Command line basics — pipes, and why they matter here
