eza, bat, and fd-find on Linux: The Modern Trio Replacing ls, cat, and find

Linux tutorial - IT technology blog
Linux tutorial - IT technology blog

2 AM. The production server threw an error. I SSHed in, typed ls -la /var/log/nginx — a wall of white text, no colors, 50 log lines blurring together. Then cat access.log to check the contents — same story, no highlighting whatsoever. I tried finding the config file with find / -name "nginx.conf" 2>/dev/null — waited 30 seconds for results, mixed in with a flood of permission errors…

That feeling is probably familiar to a lot of people. It’s not that ls, cat, or find are broken — they still work fine. But they were written in the ’70s, and modern terminals have come a long way since then.

After that incident, I started using eza, bat, and fd-find — three tools rewritten from scratch in Rust that preserve the original functionality while adding color, speed, and a much better UX. In this post, I’ll share how to install and use them in practice, without the lengthy theory.

The Problem with ls, cat, and find in Real-World Environments

On our company’s aging CentOS 7 server, I had to optimize quite a few things to hit the performance targets we needed — and one of the first things I did was replace these basic commands. Not to look cool, but because it genuinely saved me a noticeable chunk of time every day.

Here are the specific pain points I ran into:

  • ls doesn’t show colors by file type by default, no git status, no built-in tree view
  • cat just dumps raw text — no syntax highlighting, no line numbers, no scrolling support for long files
  • find has verbose syntax (find . -name "*.py" -not -path "*/node_modules/*"), slows down with large directories, and mixes permission errors into the output

Core Concepts: Three Rust Tools Replacing Classic Unix Utilities

eza — A Modern ls

eza is an actively maintained fork of exa (which is no longer in development), written in Rust. It replaces ls with per-file-type colors (executable, symlink, directory, etc.), git status shown inline in the file listing, a built-in tree view, and human-readable sizes by default.

bat — cat with Soul

bat is cat but with syntax highlighting for 150+ languages, line numbers, integrated git diff, and automatic paging for long content. The syntax is identical to cat — just swap the command name and you’re done.

fd-find — find Without the Tears

fd (packaged as fd-find on Debian/Ubuntu) is find rewritten: much simpler syntax, automatically respects .gitignore and ignores hidden directories by default, runs in parallel so it’s noticeably faster, and has full color and Unicode support.

Hands-On Walkthrough

Installing on Ubuntu/Debian

# Install eza
sudo apt update
sudo apt install eza

# Install bat
sudo apt install bat
# Note: on Debian/Ubuntu, the command is batcat (to avoid name conflicts)
mkdir -p ~/.local/bin
ln -s /usr/bin/batcat ~/.local/bin/bat

# Install fd-find
sudo apt install fd-find
# Similarly, the command is fdfind — create a symlink for convenience
ln -s $(which fdfind) ~/.local/bin/fd

Installing on CentOS/RHEL/AlmaLinux

# Download eza binary from GitHub releases (no Rust required)
EZA_VERSION="v0.19.0"
curl -Lo /tmp/eza.tar.gz \
  "https://github.com/eza-community/eza/releases/download/${EZA_VERSION}/eza_x86_64-unknown-linux-musl.tar.gz"
tar -xf /tmp/eza.tar.gz -C /tmp
sudo mv /tmp/eza /usr/local/bin/

# Download bat binary
BAT_VERSION="v0.24.0"
curl -Lo /tmp/bat.tar.gz \
  "https://github.com/sharkdp/bat/releases/download/${BAT_VERSION}/bat-${BAT_VERSION}-x86_64-unknown-linux-musl.tar.gz"
tar -xf /tmp/bat.tar.gz -C /tmp
sudo mv /tmp/bat-*/bat /usr/local/bin/

# Download fd binary
FD_VERSION="v10.1.0"
curl -Lo /tmp/fd.tar.gz \
  "https://github.com/sharkdp/fd/releases/download/${FD_VERSION}/fd-${FD_VERSION}-x86_64-unknown-linux-musl.tar.gz"
tar -xf /tmp/fd.tar.gz -C /tmp
sudo mv /tmp/fd-*/fd /usr/local/bin/

The advantage of installing binaries this way: no root access required if you install to ~/.local/bin, and it works on older servers like CentOS 7 without needing to install any additional dependencies.

Using eza Instead of ls

# Basic file listing (colors right out of the box)
eza

# Equivalent to ls -la
eza -la

# Long format + git status — incredibly useful when working with repos
eza -la --git

# Built-in tree view
eza --tree --level=2

# Tree with long format, ignoring junk directories
eza --tree --level=3 --ignore-glob="node_modules|.git|__pycache__"

# Sort by modification time, newest first
eza -la --sort=modified --reverse

# Group directories first
eza -la --group-directories-first

Add aliases to ~/.bashrc or ~/.zshrc:

alias ls='eza --color=auto'
alias ll='eza -la --git --group-directories-first'
alias lt='eza --tree --level=2 --ignore-glob=".git|node_modules"'
alias la='eza -la --group-directories-first'

Using bat Instead of cat

# View files with automatic syntax highlighting
bat nginx.conf
bat /etc/ssh/sshd_config
bat app.py

# View multiple files at once
bat *.py

# Disable line numbers and decorations when piping to other commands
bat --style=plain nginx.conf

# View only a portion of the file (lines 10-30)
bat -r 10:30 access.log

# Use bat as a pager for man pages — incredibly useful
export MANPAGER="sh -c 'col -bx | bat -l man -p'"
man nginx

The first time I used bat to read an Nginx config at 2 AM — color highlighting for each directive, clear line numbers — I tracked down the issue so much faster. It sounds like a small thing, but when your eyes are tired and your brain is fried, color makes a real difference.

Configuring a theme for bat:

# List available themes
bat --list-themes

# Preview a theme before committing
bat --theme=Dracula /etc/nginx/nginx.conf

# Set as default in config
mkdir -p ~/.config/bat
echo '--theme="Dracula"' >> ~/.config/bat/config

Using fd Instead of find

# Search by filename — much simpler than find
fd nginx.conf
fd "*.log"
# find equivalent: find . -name "nginx.conf"

# Search in a specific directory
fd nginx.conf /etc

# Search by extension
fd -e py           # all .py files
fd -e log /var     # .log files in /var

# Include hidden files (fd skips them by default)
fd -H ".env"

# Search by type: f=file, d=directory, l=symlink
fd -t f "*.conf" /etc
fd -t d "logs"

# Execute a command on each result
fd -e log --older-than 30d /var/log -x rm {}

# Find files larger than 100MB
fd -S +100M /var

# Find files modified in the last 7 days
fd --changed-within 7d -e conf /etc

fd uses regex syntax, so fd "access.*log" matches both access.log and access_error.log in a single run. find requires different glob patterns and is significantly more verbose.

Combining All Three Tools

The real power comes when you use them together:

# Find recently modified config files and view each one
fd -e conf --changed-within 7d /etc | xargs bat

# View project structure, ignoring build artifacts
eza --tree --level=3 --ignore-glob="node_modules|__pycache__|.git|dist|build"

# Find Python files containing TODO and view their contents
fd -e py | xargs grep -l "TODO" | xargs bat

# Find large logs and view the last 100 lines with syntax highlighting
fd -S +10M -e log /var/log | xargs -I{} bat -r -100: {}

Full Setup in Your Shell Config

# Add to ~/.bashrc or ~/.zshrc

# eza
alias ls='eza --color=auto'
alias ll='eza -la --git --group-directories-first'
alias lt='eza --tree --level=2 --ignore-glob=".git|node_modules"'
alias la='eza -la --group-directories-first'

# bat
alias cat='bat --style=auto'
alias catp='bat --style=plain'   # plain output when piping
export MANPAGER="sh -c 'col -bx | bat -l man -p'"

# fd (on Ubuntu/Debian)
alias fd='fdfind'

# Apply immediately
source ~/.bashrc

Conclusion

These three tools don’t change your workflow — they just make everything more comfortable. eza lets you see git status at a glance while working in a repo, bat lets you read configs and code without opening an editor, and fd finds files quickly without needing to memorize find‘s complex syntax.

Install once, set up aliases, and you’re done — no need to relearn anything since the interface is nearly identical to the original tools. Next time there’s a 2 AM incident, at least the terminal will look a little friendlier, and you’ll track down the error a bit faster. Sometimes that’s all it takes.

Share: