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              # macOS

On 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/bat

Prefer 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

catlessbat
Syntax highlightingNoNoYes
Line numberscat -nless -NYes, by default
Pages long files automaticallyNoYesYes
Shows git modificationsNoNoYes
Shows non-printing characterscat -APartially-A
Concatenates filesYesNoYes
Safe in a pipeYesn/aNeeds care
Installed everywhereYesYesNo

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-themes

bat -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. cat passes 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; cat and xxd are what you want for anything else.
  • Machines you do not control. The usual reason, and the reason the cat habit 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=always

The --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 wantCommand
Read a file properlybat file
Only lines 40–60bat -r 40:60 file
No decoration, for copyingbat -p file
Reveal tabs and trailing spacesbat -A file
Force a syntaxbat -l yaml file
Coloured man pagesSet MANPAGER, see above
Feed a pipelinecat file | ...
Open a huge logless file, then / to search
Follow a growing file, scrollablyless +F file
Debian: it is calledbatcat

Related reading