Modern Replacements: bat, eza, zoxide
Replace cat, ls, and cd with bat, eza, and zoxide for syntax highlighting, richer file listings, and instant directory jumping — with safe shell aliases.
Before you start
- ▸A working terminal with bash, zsh, or fish
- ▸sudo or root access to install packages
- ▸curl installed (for zoxide fallback install script)
- ▸Basic familiarity with editing shell RC files (~/.bashrc or ~/.zshrc)
The classic Unix tools cat, ls, and cd work fine, but bat, eza, and zoxide make daily terminal work noticeably faster and more readable. This guide walks through installing all three, validating they work, and wiring up safe aliases so you keep backward compatibility.
What You Are Replacing and Why
- bat replaces
cat: syntax highlighting, line numbers, Git change markers, and automatic paging for long files. - eza replaces
ls: colour-coded output, Git status column, icon support, better tree mode. Eza is the actively maintained fork of the now-archived exa. - zoxide replaces
cd: remembers your most-visited directories and lets you jump to them with a short fuzzy substring instead of a full path.
None of these break existing scripts. Aliases only affect your interactive shell; scripts that call /bin/ls, /bin/cat, or use cd as a built-in are unaffected as long as you alias carefully.
Installing bat
Debian / Ubuntu
The package has been in Debian since Bullseye and Ubuntu since 20.04, but the package name collides with another tool on older releases, so confirm what you get:
sudo apt install bat
On Ubuntu 20.04 and some Debian versions the binary is installed as batcat, not bat, to avoid the name clash. Check with:
which bat || which batcat
If you only have batcat, add a personal symlink so the alias below works uniformly:
mkdir -p ~/.local/bin
ln -s "$(which batcat)" ~/.local/bin/bat
Make sure ~/.local/bin is on your PATH (it usually is on modern Ubuntu; if not, add export PATH="$HOME/.local/bin:$PATH" to your shell RC).
Fedora / RHEL 9+ / Rocky 9+
sudo dnf install bat
Arch Linux
sudo pacman -S bat
Installing eza
Eza is newer than exa and is not yet in all default repositories. Check first; fall back to the official release tarball if needed.
Debian / Ubuntu (22.04+)
Eza maintains an official apt repository:
sudo apt install -y gpg
wget -qO- https://raw.githubusercontent.com/eza-community/eza/main/deb.asc \
| sudo gpg --dearmor -o /etc/apt/keyrings/eza.gpg
echo "deb [signed-by=/etc/apt/keyrings/eza.gpg] http://deb.gierens.de stable main" \
| sudo tee /etc/apt/sources.list.d/eza.list
sudo apt update
sudo apt install eza
Fedora
sudo dnf install eza
Arch Linux
sudo pacman -S eza
Icon support (optional)
Eza can show file-type icons with --icons, but only if your terminal uses a Nerd Font. Install one from nerdfonts.com and set it in your terminal emulator. Without a Nerd Font the flag still works but outputs garbled characters.
Installing zoxide
Debian / Ubuntu
sudo apt install zoxide
If the package is too old or absent, use the upstream installer script (it places a static binary in ~/.local/bin):
curl -sSfL https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh | sh
Fedora / RHEL / Rocky
sudo dnf install zoxide
Arch Linux
sudo pacman -S zoxide
Shell initialisation — required step
Zoxide needs a hook in your shell to record every directory you visit. Add the appropriate line to your shell RC file, then reload it.
bash — add to ~/.bashrc:
eval "$(zoxide init bash)"
zsh — add to ~/.zshrc:
eval "$(zoxide init zsh)"
fish — add to ~/.config/fish/config.fish:
zoxide init fish | source
After editing, reload:
source ~/.bashrc # or ~/.zshrc
Setting Up Safe Aliases
Aliases below override the default commands in interactive sessions only. They include fallback guards so your shell does not break if a tool is temporarily absent.
Add the following block to ~/.bashrc (or ~/.zshrc), after the zoxide init line:
# bat — syntax-highlighted cat
if command -v bat >/dev/null 2>&1; then
alias cat='bat --paging=never'
alias less='bat'
elif command -v batcat >/dev/null 2>&1; then
alias cat='batcat --paging=never'
alias less='batcat'
fi
# eza — modern ls
if command -v eza >/dev/null 2>&1; then
alias ls='eza --group-directories-first'
alias ll='eza -lh --group-directories-first --git'
alias la='eza -lah --group-directories-first --git'
alias lt='eza --tree --level=2'
fi
# zoxide — smarter cd
# 'z' is the zoxide jump command added by init above.
# Optionally shadow 'cd' itself — only do this if you are comfortable:
# alias cd='z'
The cd='z' alias is commented out deliberately. Zoxide's z command does not handle some edge cases that cd handles (such as cd - for going back, or bare cd to go home) equally well in all shells. Use z as a complement rather than a full replacement until you are confident. In bash and zsh, cd - and cd alone still work normally alongside z.
Verifying the Setup
Open a new terminal (or run source ~/.bashrc) and run a quick sanity check:
# bat
bat --version
cat /etc/os-release # should show highlighted output
# eza
eza --version
ls /etc # colour, grouped directories
ll /usr/bin # long format with git column
lt /etc # tree, 2 levels deep
# zoxide — visit a few dirs first so it learns them
cd ~/Downloads && cd ~/Documents && cd /tmp
z Down # should jump to ~/Downloads
pwd # confirm
Expected z Down output: your shell prompt moves to /home/yourname/Downloads. The first time you use zoxide it needs a few visits before the ranking is meaningful.
Useful Flags to Know
| Tool | Flag | Effect |
|---|---|---|
| bat | -n | Line numbers only, no syntax theme |
| bat | --plain | Raw output, useful in pipes |
| bat | -l json | Force JSON highlighting on extensionless files |
| eza | --icons | File-type icons (needs Nerd Font) |
| eza | --git | Show Git status per file |
| eza | --color=never | Pipe-safe plain output |
| zoxide | zi | Interactive fuzzy picker (requires fzf) |
| zoxide | zoxide query -l | List all remembered directories by score |
Troubleshooting
- bat shows no colour in pipes: bat detects pipe context and strips colour. Force it with
bat --color=alwayswhen piping to another tool likegrep. - eza says "unknown flag --icons": You have the old exa package installed, not eza. Confirm with
eza --version; the output should say eza. Remove exa and reinstall. - zoxide does not jump anywhere: The init line is missing or the shell was not reloaded. Run
type z; if it returns "not found", re-check your RC file and reload. - zi (interactive mode) errors:
zirequiresfzf. Install it with your package manager (apt install fzf,dnf install fzf,pacman -S fzf). - Aliases break a script: Scripts use their own non-interactive shell and do not load your
~/.bashrcaliases. If a script breaks, it was calling the command by name without a full path and you've changed something else — aliases are not the cause.
Frequently asked questions
- Will aliasing cat to bat break shell scripts?
- No. Shell aliases only apply in interactive sessions. Scripts run in a non-interactive subshell that does not source ~/.bashrc aliases, so /bin/cat is always called directly.
- Is eza the same as exa?
- No. Exa is archived and no longer maintained. Eza is a community fork that continues active development. If your package manager installs exa, check for an eza package or add the official eza repository.
- How does zoxide decide which directory to jump to?
- Zoxide scores directories by a combination of how frequently and how recently you have visited them (a frecency algorithm). The highest-scoring match for your query is selected.
- Can I use these tools over SSH without reinstalling them on every server?
- You need them installed on the remote host for remote sessions. However, you can keep a personal ~/.local/bin with statically compiled binaries and rsync that directory to remote machines you manage regularly.
- bat seems slow on very large files — what should I do?
- Use bat --paging=always for large files so it pages through them, or use --plain to skip syntax highlighting entirely. For files over a few megabytes, piping to plain less is still the faster option.
Related guides
Bash Arrays and Associative Arrays
Master bash indexed and associative arrays: declaration, element access, looping, mapfile, namerefs, and practical patterns for real scripting work.
Bash Functions and Variable Scoping
Master Bash function scoping with local variables, source-based libraries, correct use of return codes, and array passing techniques including namerefs.
Bash Loops: for, while and until
Learn all three Bash loop types — for, while, and until — with practical, copy-paste examples covering file iteration, counting, polling, and safe line reading.
Bash Scripting for Beginners
Learn Bash scripting from scratch: shebang lines, variables, conditionals, loops, and arguments, plus a real backup script to tie it all together.