bat: A cat Clone with Syntax Highlighting
What you'll be able to do
- Display files with color and line numbers using `bat`
- Fix the Ubuntu `batcat` naming issue yourself
- Strip decorations with `-p` and `-pp` to match `cat` output
Prerequisites (read these first)
What You'll Learn
- How to use
batinstead ofcatto display files with color and line numbers - How to fix the Ubuntu/Debian
batcatissue (the command isn't namedbat) - How to strip decorations to match
cat's output for pipes and scripts - Practical extras like coloring
manpages that pay off daily
Target Audience: Linux beginners, anyone underwhelmed by cat's plain output
Words used here (sorted out first)
- Syntax highlighting: coloring text by its grammar. "Color-coding the syntax" means the same thing.
- Pager: a tool that shows a long file one screen at a time.
lessis the classic one. - Standard output: where a command's result goes. Normally that is your screen.
- Pipe: the
|symbol. It hands the left command's result to the right command. - Symlink: a shortcut that points at the same thing under another name.
PATH: the list of places the shellAn interactive program that reads the commands you type and runs them. searches for commands. A command outside those places cannot be called by name alone.
Introduction: Lina's "cat Is Hard to Read" Problem
cat config.json, but everything's the same color and my eyes just slide right off it. Reopening it in an editor is a hassle, too.cat just "dumps the contents as-is" — no color, no line numbers. There's an upgraded cat called bat that makes it readable in one shot.cat. Syntax highlighting, line numbers, even Git diff markers — all built in from the start. Let's learn it together today.The Short Answer
bat= acatreplacement with color, line numbers, Git diffs, and automatic paging out of the box- On Ubuntu/Debian,
sudo apt install batinstalls it but the command isbatcat(aliasing it tobatis standard) - For pipes and scripts,
bat -p(no decorations) /bat -pp(no pager either) bring you back tocat-like behavior
1. What Is bat?
Conclusion:
batis acatreplacement. It displays file contents just likecat, but adds syntax highlighting, line numbers, Git change markers, and automatic paging.
bat and cat?cat streams plain black-and-white text, bat color-codes the syntax, adds line numbers, and even marks changed lines when you're in a Git repo.cat?bat covers almost all of it. It isn't a perfect drop-in replacement, though, so you need a little care in pipes and scripts. We'll cover that later.bat is a Rust tool developed by sharkdp/bat. The main differences from cat:
| Aspect | cat | bat |
|---|---|---|
| Syntax highlighting | None | Yes (auto-detects the language) |
| Line numbers | With -n |
On by default |
| Git diff display | None | Yes (marks changed lines) |
| Long files | Scroll past all | Auto-launches less (a pager) |
| Non-printable chars | -A symbolizes |
-A symbolizes |
| Behavior in a pipe | Always plain text | Auto-disables decorations (later) |
2. Install and the batcat Issue
Conclusion: On Ubuntu/Debian,
apt install batworks, but the command is namedbatcatto avoid a name clash. Symlinking it tobatis the standard fix.
# Ubuntu / Debian family $ sudo apt install bat # Fedora / RHEL family $ sudo dnf install bat # Arch Linux $ sudo pacman -S bat # macOS (Homebrew) $ brew install bat
The Ubuntu/Debian Trap: the Command Is batcat
On Debian, to avoid a binary name clash with another package, the command is named batcat instead of bat. Typing bat gives you command not found.
sudo apt install bat succeeded. But bat config.json says bat: command not found. Did the install fail?batcat. Try batcat --version.fdfind issue with fd. Add a symlink and you can call it as bat.To use it under the name bat, create a symlink in ~/.local/bin.
mkdir -p ~/.local/bin ln -sf "$(which batcat)" ~/.local/bin/bat
-f is there so the command still works when a link of that name already exists.
First check whether ~/.local/bin is on your PATH.
$ echo $PATH
If /home/username/.local/bin appears in the output, you can skip the next step. Only continue when it is missing.
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc source ~/.bashrc
Don't mix up >> and >
>>appends to the end. What was already there stays>wipes the file and rewrites it. Using>here erases everything in~/.bashrc- Erased content cannot be recovered. Nothing goes to a trash folderA container that organizes files. Same idea as a "folder" on Windows or macOS.
- This edits a real settings file on your machine.
batdoes not run in this site's virtual terminal, so run it in your own terminal - Take a copy before you run it
$ cp ~/.bashrc ~/.bashrc.bak
- If you typed
>by mistake, restore it withcp ~/.bashrc.bak ~/.bashrc
What source does
~/.bashrc is read "when you open a new terminal." Appending to it does not affect the terminal you already have open. source ~/.bashrc says "re-read it right now." Opening a new terminal has the same effect.
Confirm the install and version:
$ bat --version
bat 0.24.0
The number varies by system. Any version string means the install worked.
If You Skip the Symlink on Ubuntu
If the symlink feels like a hassle, you can read every bat in this article's examples as batcat and it still works. But the symlink lets you copy-paste bat from other articles and docs as-is, which is more convenient.
3. The Basics of Using bat
Conclusion:
bat FILENAMEshows the contents with color and line numbers. Pass multiple files and it separates them with labeled headers.
cat — just pass the filename you want to display. Let's make a file to try the coloring on.$ mkdir -p ~/bat-practice
$ cd ~/bat-practice
$ printf '{\n "name": "penguin",\n "version": "1.0.0",\n "debug": false\n}\n' > config.json$ bat config.json
───────┬────────────────────────────────────────
│ File: config.json
───────┼────────────────────────────────────────
1 │ {
2 │ "name": "penguin",
3 │ "version": "1.0.0",
4 │ "debug": false
5 │ }
───────┴────────────────────────────────────────
How to Read It
- The numbers on the left: line numbers (the
cat -nequivalent, on by default) - The top
File: config.json: the header with the file name - The colors: the language is auto-detected from the extension and syntax-highlighted (JSON above)
Pass multiple files and each gets its own header as a separator.
$ bat a.txt b.txt
cat a.txt b.txt the contents ran together and I couldn't tell where b.txt started.bat inserts a header per file, so checking multiple files gets much easier.Long Files Become a Pager Automatically
Open a file too long for the screen with bat and it automatically launches less (a pager). Scroll with the arrow keys or Space, and quit with q. You won't lose your place to a cat-style flood scrolling off the screen.
4. How Do I Make It Plain Like cat?
Conclusion: To strip decorations (line numbers, header, grid lines), use
-p(--plain). To also stop the pager and behave almost likecat, use-pp.
# Strip line numbers, header, and grid (keep color) $ bat -p config.json # Strip decorations AND the pager (almost identical to cat) $ bat -pp config.json
Two Levels of Stripping Decorations
| Option | What's removed | What stays |
|---|---|---|
-p |
Line numbers, header, grid | Color, automatic paging |
-pp |
All of the above + automatic paging | Color (on a terminal) |
-p twice is -pp. Easy to remember.-pp means "no decorations, no pager," so it's an easy drop-in for cat. It's the go-to when you just want a quick look at the contents.To inspect non-printable characters (tabs, line endings, trailing spaces), use -A (--show-all).
$ bat -A messy.txt
-A visualizes tabs as ├──▶ and newlines as a ␊-like symbol. It's great for "invisible whitespace breaks my script" troubleshooting. Same purpose as cat -A, but the color makes it clearer.
5. How Do I Customize the Display?
Conclusion: Choose which parts to show with
--style(numbers / header / grid / changes, etc.), and change the colors with--theme. List available themes with--list-themes.
--style you specify the components to show, comma-separated.# Line numbers only (no grid, no header) $ bat --style=numbers config.json # Line numbers and Git change markers only $ bat --style=numbers,changes config.json # Strip all decorations (same as -p) $ bat --style=plain config.json
Main Components for --style
| Value | Meaning |
|---|---|
numbers |
Line numbers |
header |
File name header |
grid |
Separator grid lines |
changes |
Git change markers |
full |
Everything |
plain |
Nothing (equivalent to -p) |
Change the color theme with --theme. List the available themes with --list-themes.
# See the list of themes $ bat --list-themes # Display with a chosen theme $ bat --theme=ansi config.json
Make Settings Permanent
If typing options every time is a chore, write defaults into a config file. Generate a template with bat --generate-config-file, set your default --theme and --style there, and from then on a bare bat applies those settings.
6. How Do I View or Highlight Specific Lines?
Conclusion: Specify a line range with
-r(--line-range) asstart:end. Make a specific line stand out with-H(--highlight-line). Force a language with-l(--language).
-r. No need for tail or sed — bat alone slices it out.# Show lines 100 through 120 $ bat -r 100:120 app.log # From line 50 to the end $ bat -r 50: app.log # From the start through line 30 $ bat -r :30 app.log
To make a specific line stand out with color, use -H.
# Display the whole file while highlighting line 42 $ bat -H 42 app.log
When the language isn't auto-detected (for files without an extension, say), specify it with -l.
# Highlight an extensionless file as JSON $ bat -l json mydata
bat guesses the language from the extension and contents, but it can miss. When it does, -l tells it "this is JSON." See the supported languages with bat --list-languages.7. What to Watch for in Pipes and Scripts?
Conclusion: When the output goes to a pipe or a file,
batautomatically strips decorations and emits plain text. Even so, it's not a perfectcatreplacement, so prefercatin scripts.
bat config.json | grep debug and it worked normally. The color codes didn't get mixed in.bat checks whether the output is a terminal (the screen), and when you pipe or redirect to a file, it auto-disables decorations and color. So passing it to grep or wc doesn't break anything.# Piping yields plain text automatically $ bat config.json | grep debug # Redirecting to a file inserts no color codes $ bat config.json > copy.json
Use cat in Scripts
bat is handy, but it isn't installed everywhere. If a shell script assumes bat, it breaks on a machine that lacks it. In scripts you distribute or share, use plain cat for processing that doesn't need decoration. Treat bat strictly as a tool for "when a human is looking."
alias cat=bat to replace cat entirely?cat's plain behavior, so overriding it with an alias can cause surprises. If anything, add it under a separate name, like alias bat='batcat'.8. What Are the Practical Extras?
Conclusion:
batcan also colorizemanpages and power previews in tools likefzf. Anywhere you want "show contents in color," you can drop it in.
bat on its own. Quietly effective once set up.To colorize man pages with bat, set the MANPAGER environment variableA named value that the shell or a program can look up while running.. Add this line at the end of ~/.bashrc, then re-read it with source ~/.bashrc.
export MANPAGER="sh -c 'col -bx | bat -l man -p'"
On Ubuntu / Debian without the symlink, rewrite the bat above as batcat. Forget that and man shows nothing when you open it. The same applies to the fzf example below.
How to Read It
col -bx: cleans up control characters inmanoutput (like overstrike-based bold)bat -l man -p: colorizes it using themanlanguage rules and displays it plainly (-p)- After setting it, opening
man lsand the like color-codes headings and options for easier reading
Used as a preview in fzf (a fuzzy finder), it shows candidate file contents in color.
# Pick a file while previewing its contents in color
$ fzf --preview 'bat --color=always {}'--color=always?fzf preview pane can be judged as "not a terminal," and left alone, bat would strip the color. So you explicitly say "always colorize." Conversely, in normal pipes you don't add it — that's the trade-off to learn.9. Mini Exercises: Try It on Your Box
Conclusion: Three drills — display, strip decorations, and a line range — to lock in
bat's basics.
These exercises only read ~/.bashrc. Nothing gets written, so you can relax.
Exercise 1: Open ~/.bashrc with bat and confirm it shows line numbers and color.
Show Hint 1 (Direction)
Usage is the same as cat. Just pass the file name; no options needed.
Show Hint 2 (Command name)
Run bat ~/.bashrc. On Ubuntu without the symlink, read that as batcat.
Show Answer
$ bat ~/.bashrc
You get line numbers on the left and a file-name header on top. Shell-script syntax highlighting means it worked. If the file is long, the pager opens; quit with q.
Exercise 2: Open the same file so the decorations and pager are gone, matching cat.
Show Hint 1 (Direction)
Repeat the decoration-stripping option twice. Once still leaves color and the pager.
Show Hint 2 (Command name)
Run bat -pp ~/.bashrc.
Show Answer
$ bat -pp ~/.bashrc
Line numbers, header, and grid disappear. The pager doesn't launch and it prints all at once — nearly identical to cat ~/.bashrc (only the color remains on a terminal).
Exercise 3: Show only the first 10 lines of ~/.bashrc.
Show Hint 1 (Direction)
There is an option for a line range. You write it as start:end.
Show Hint 2 (Command name)
Use bat -r. Starting from the top, you may omit the start.
Show Answer
$ bat -r 1:10 ~/.bashrc
bat -r :10 ~/.bashrc gives the same result. Try bat -r 5: ~/.bashrc (from line 5) too, to get a feel for ranges.
Looking Back
Conclusion: bat for looking at files, cat for handing them to something else.
bat, add -pp when I want to copy, use -r to narrow the range.cat. Remember bat as the tool for "when a human is looking" and you won't get stuck.command not found on Ubuntu won't scare me now. The command is just called batcat.Three-Line Recap
Conclusion: bat is the readable stand-in for cat, and
-ppstrips it back down.
bat FILENAMEshows a file with color and line numbers- If Ubuntu says
bat: command not found, the command is simply namedbatcat - Add
-ppfor pipes and copying. In scripts, stick with plaincat