32blogby Studio Mitsu

batでcatを置き換える シンタックスハイライトとgit連携

bat は Rust 製の cat 置き換えツール。シンタックスハイライト・git 差分・ページャ連携を設定ファイルレシピで実戦解説する。

by omitsu22 min read
目次

bat は Rust 製の cat 置き換えツール。200 以上の言語でシンタックスハイライトを効かせ、git の差分を左側のガッターで表示し、less へ自動でページャ連携する。apt install batbrew install bat で入れて ~/.config/bat/config で好みの設定を決め、.bashrcalias cat='bat --paging=never' を1行足すだけで、手癖を変えずにファイルビューアを丸ごと置き換えられる。

あなたのターミナルで cat src/app.ts を叩いた時の出力、1983年から進化していない気がしないだろうか。色なし、行番号なし、どの行が最後のコミットで変わったのかも見えない。長いファイルは一瞬でスクロールアウトして、結局 を押し直して less で開き直すことになる。しかもその less が、せっかく設定したターミナルテーマを無視してモノクロで出てくる。この微妙なストレスを丸ごと解消するのが bat だ。

シンタックスハイライト付きファイルビューアという発想自体は昔からあったが、ここまで普及したのは bat が初めてだと思う。理由は単純で、cat の置き換えとして違和感がない、** 十分に速いのでエイリアスで常用できる**、そして** デフォルトの見た目がそのまま気持ちいい**の3点が揃っているからだ。この記事では「インストールして終わり」のレベルを越えて、設定ファイル・git 連携・シェルの他ツールとの組み合わせまで実戦レシピで掘り下げていく。

cat で解決できなかった4つの問題

cat は 1971 年に生まれた concatenate(連結)のためのコマンドだ。本来の役割はファイルを連結して標準出力に流すことで、「ファイルを見る」のはたまたま便利だっただけ。今 cat に感じる不満は全部、連結ツールにビューアの仕事をさせていることが原因だ。

bat は次の4点を正面から解決している。

  1. シンタックスハイライトcat はファイルの中身を一切パースしないから、文字列リテラルを青に、キーワードをマゼンタに色付けることは原理的にできない。bat は 200 以上の言語を組み込みでサポートしており、内部では Sublime Text と同じ .sublime-syntax 形式で シンタックス定義 を持っている。
  2. 行番号・ヘッダ・グリッドcat -n で行番号は出るが、それだけ。bat はファイル名のヘッダ、ヘッダと本文を区切るグリッド、薄い色の行番号ガッターまで表示する。見た目はコードレビューツールそのもの。
  3. 自動ページャ。ファイルが画面より長いと cat は一気に流して先頭は永遠に失われる。bat は TTY を判定して less に良いオプションを渡して起動してくれる。逆にパイプに繋いだ時はプレーン出力にフォールバックする。
  4. git 連携。bat は .git を読んで、追加・変更・削除された行を左ガッターにマーカーで表示する。VS Code のエディタ左側と同じ記号だ。これだけでも入れる価値がある。

bat をインストールする(batcat 問題に注意)

インストールは1コマンドだが、Ubuntu/Debian で1か所だけハマりポイントがある。

powershell
# winget(Windows 11 標準搭載)
winget install sharkdp.bat

# Chocolatey
choco install bat

# Scoop
scoop install bat

Windows では PowerShell、Windows Terminal、WSL のいずれでも動く。24-bit カラーを出したいなら Windows Terminal を使うこと。PowerShell の旧コンソールは一部のテーマで色が崩れる。

インストールできたらバージョンと --help を1回見ておくと全オプションの雰囲気が掴める。

bash
bat --version
# bat 0.26.1 以上

bat --help | less

日常で使う9パターン

ほとんどの場合、bat は bat filename という cat と同じ使い方で十分だ。でも現場では次の9パターンを覚えておくとほぼ網羅できる。上から順番に見ていけば、だいたいのユースケースはカバーできる。

bash
# 1. シンタックスハイライト付きで1ファイル表示(デフォルト動作)
bat src/app.ts

# 2. 複数ファイルを連結表示(cat a b c と同じ感覚)
bat README.md package.json src/main.ts

# 3. 途中に標準入力を挟んで連結(cat と同じく - が stdin)
echo "--- header ---" | bat header.md - footer.md

# 4. 拡張子が変な時に言語を明示する
bat -l json config.txt
bat -l dockerfile Containerfile

# 5. 行範囲だけ表示(Issue に貼る時に便利)
bat --line-range=42:80 src/handlers.ts
bat --line-range=:50 README.md   # 先頭50行だけ

# 6. 装飾なし・ページャなしで cat 互換の出力
bat -p src/app.ts
bat --plain --paging=never src/app.ts

# 7. 不可視文字(タブ・末尾スペース・CRLF)を可視化
bat -A Makefile

# 8. 他コマンドからパイプで受け取って言語を指定
curl -s https://api.github.com/repos/sharkdp/bat | bat -l json

# 9. git 差分がある行だけ抽出表示
bat --diff src/app.ts

一番出番が多いのは個人的に --line-range だ。Slack や Issue で「あのファイルの200行目付近って何してたっけ?」と聞かれた時、bat --line-range=190:220 path/to/file.ts の出力をそのまま貼れば、行番号とシンタックスハイライト付きの抜粋が一発で送れる。

~/.config/bat/config で一度だけ設定する

毎回フラグを打ち続けるのはすぐ面倒になる。bat には1行1フラグ形式の設定ファイル があり、コマンドラインで書くのと同じ書式をそのまま羅列できる。この設定ファイルを埋めた瞬間、bat は「一時的な便利ツール」から「常駐インフラ」に昇格する。

まず設定ファイルの場所を確認する。

bash
bat --config-file
# Linux:   /home/あなた/.config/bat/config
# macOS:   /Users/あなた/.config/bat/config
# Windows: C:\Users\あなた\AppData\Roaming\bat\config

bat --generate-config-file
# ファイルがなければデフォルト内容で作成する

現場で使えるスタート設定はこんな感じ。

bash
# ~/.config/bat/config

# ダークターミナル向けの定番テーマ
--theme="OneHalfDark"

# 行番号と git 差分だけ表示(ヘッダとグリッドは出さない)
--style="numbers,changes"

# タブ幅2(今どきの JS/TS プロジェクト準拠)
--tabs=2

# プロジェクト固有ファイル名のシンタックス紐付け
--map-syntax=".ignore:Git Ignore"
--map-syntax="*.conf:INI"
--map-syntax="Dockerfile.*:Dockerfile"

# ページャに less を明示指定(終了時に出力を残す -F と ANSI 透過 -R)
--pager="less -FR"

この設定ファイルを置いた瞬間から、bat を叩くたびにこれらのデフォルトが適用される。もちろんコマンドライン側で個別に上書きも可能で、bat --theme=GitHub README.md のように一時的にライトテーマで見ることもできる。

テーマ

bat には約25種類のテーマが同梱されている。一覧は次のコマンドで見られる。

bash
bat --list-themes

この一覧は単なる名前の羅列ではなく、各テーマの下にコードサンプルが実際の色で表示されるので、ターミナル背景との相性を見てから選べる。個人的な推奨はダーク系なら OneHalfDark、ライト系なら GitHub だが、好みの問題なので1回全部眺めてみるといい。Sublime Text の .tmTheme ファイルを持っているなら $(bat --config-dir)/themes/ に放り込んで bat cache --build で取り込める。

環境変数

設定ファイルと同じ項目は環境変数でも指定できる。シェルごと・プロジェクトごとに一時的に挙動を変えたい時に便利だ。

変数名設定フラグ相当用途
BAT_THEME--theme=...ターミナル/プロジェクト別のテーマ切り替え
BAT_STYLE--style=...スクリプトでは plain、対話シェルでは full
BAT_PAGER--pager=...特定環境だけ別のページャに差し替える
BAT_PAGING--paging=...never に固定して cat 互換にする
BAT_CONFIG_PATHプロジェクトローカルの設定ファイルを指す

全リストは README の customization セクション にある。

git 連携:左ガッターの差分マーカーと --diff

bat には git のことを明示的に教える必要はない。リポジトリの中で bat src/app.ts を叩けば、HEAD と比べて追加・変更・削除された行に +~- のマーカーが左ガッターに自動で出る。内部では git2 という libgit2 の Rust バインディングを使ってリポジトリ状態を直接読んでいる。

この差分表示の使い方は2通りある。

bash
# 1. 自動表示:style に "changes" が含まれていれば勝手にマーカーが出る
bat src/app.ts

# 2. 差分行だけ抜き出す
bat --diff src/app.ts

bat --diffxargs を組み合わせれば、「今さわった全ファイルの変更箇所だけシンタックスハイライト付きで見る」が一発で実現する。

bash
git diff --name-only -z | xargs -0 bat --diff

bat で git loggit show の出力まで色付けしたいなら delta という diff 専用ツールの方が向いている。delta 単独の深掘りは delta 設定レシピ記事 にまとめてあるので、bat の --diff モードでは物足りなくなったらそちらへ。

他ツールとの連携:man・fzf・ripgrep・less

bat がシェル環境の中心に居座る理由は、ほぼ全ての CLI ツールが bat を経由させられることにある。特に効くのが次の4つの連携だ。どれも1週間使えば十分に元が取れる。

シンタックスハイライト付きの man ページ

MANPAGER 環境変数に、man が出力する生の ANSI 制御シーケンスを剥がして bat に流すシェルコマンドを指定する。

bash
# ~/.bashrc か ~/.zshrc に追加(Debian/Ubuntu では `bat` を `batcat` に置き換える)
export MANPAGER="sh -c 'awk '\''{ gsub(/\x1B\[[0-9;]*m/, \"\", \$0); gsub(/.\x08/, \"\", \$0); print }'\'' | bat -p -lman'"

これで man ffmpegman gitman bash が色付きで読めるようになる。セクション見出しは強調、オプションは太字、フラグはハイライト。README の --help 強調セクション に紹介されているスニペットで、一度入れたら戻れない系の設定だ。

fzf のプレビュー

fzf はファジーファインダで、--preview フラグで候補ごとに任意のコマンドを実行して結果を横に出せる。これを bat に向けるとシンタックスハイライト付きのプレビューが手に入る。

bash
# ~/.bashrc か ~/.zshrc
export FZF_DEFAULT_OPTS="--preview 'bat --color=always --style=numbers --line-range=:500 {}'"

ここで --color=always が重要。fzf はプレビューコマンドを標準出力がパイプに繋がった状態で起動するので、bat は普通なら色を落とす。明示的に always を指定しないとハイライトが効かない。--line-range=:500 を入れておくのは、1万行のファイルを毎回全部レンダリングさせると体感でカクつくからだ。

ripgrep の結果を bat で見る

ripgrep は別記事で深掘り中 だが、bat との組み合わせは bat-extras に含まれる batgrep ラッパが担当してくれる。batgrep foo と叩くと ripgrep で foo を検索し、ヒット箇所を bat のハイライト+前後数行の文脈付きで出してくれる。CLI 版の「定義にジャンプ」に一番近い体験だ。

less も bat 経由にする

bat は内部的に less をページャとして使っているが、逆の繋ぎ方もできる。LESSOPEN を設定して、less がファイルを開く時に bat を経由させる 方向だ。

bash
# ~/.bashrc
export LESSOPEN="|bat --color=always --style=numbers --paging=never %s"
export LESS="-R"

これで git showsystemctl catjournalctl など less を内部で呼ぶツール全般が bat のハイライトで出てくるようになる。ただし「less は単純なページャである」という前提に依存している他ツールと稀に相性問題を起こすことがあるので、最初は慎重に入れて問題が起きたら外す運用が安全だ。

FAQ

bat は cat を完全に置き換えていいの?

対話シェルでの閲覧なら完全に置き換えてよし。シェルスクリプトの中では cat のままにしておくこと。 スクリプトの中で cat を bat エイリアスに置き換えるとバイト列が変わってしまう可能性がある(色コードが紛れ込む等)。alias cat='bat --paging=never'.bashrc に書くのは安全だ。.bashrc は非対話シェルでは読み込まれないのでスクリプトには影響しない。

bat の出力をパイプに流したら色が消えたんだけど

bat は標準出力が TTY かどうかを自動判定して、パイプに繋がっていると色をオフにする仕様だ。これは lsgrep と同じ慣習で、--color=always を明示すれば強制的に色付きで出せる。

git の core.pager に bat を使える?

使える。

bash
git config --global core.pager "bat --plain"

ただし git の差分表示を本気でカッコよくしたいなら delta の方が上位互換だ。bat をページャに使う方式は軽量で悪くないけれど、side-by-side 表示や行番号付きの差分表示が欲しいなら delta 一択になる。

bat のテーマはターミナルのテーマを読んでくれる?

部分的に。bat は自分のテーマリストから選ぶ方式で、ターミナルの 16 色パレットを ls --color=auto のように読み込むわけではない。ターミナルテーマと揃えたいなら bat --list-themes で似た雰囲気のものを選ぶか、BAT_THEME_DARKBAT_THEME_LIGHT の両方を設定して COLORFGBG 環境変数で自動切り替えさせる方式が使える。

大きいファイルで bat は cat より遅い?

計測上は遅いが、実用上は気にならない。 100 MB のログファイルだと cat のほうが明らかに速い(bat は全行パースしているから当然)。一方でソースコード・設定ファイル・README のサイズではまず体感できない差になる。巨大ファイルを流す時は bat --plain --paging=never か素の cat を使えばいい。

独自シンタックスやテーマを追加したい

できる。$(bat --config-dir)/syntaxes/.sublime-syntax ファイル、$(bat --config-dir)/themes/.tmTheme ファイルを置いて、キャッシュを再構築する。

bash
bat cache --build

Sublime Text 向けのテーマとシンタックスがほぼそのまま流用できる。詳しい手順は README のシンタックス追加セクション にある。

less にシンタックスハイライトを付ければ bat は要らないのでは?

原理的にはその通りで、LESSOPEN のトリックで似たようなことはできる。でも bat が提供するのはその設定一式をゼロコンフィグで持ってきてくれるパッケージだ。「今から catless を設計するならこうなるよね」というのが bat の立ち位置 で、自分で配線を組む手間がかからないのが最大の価値。

まとめ

モダン Rust CLI ツールまとめ の中から今週1つだけ入れるなら bat を選ぶと間違いがない。インストールは30秒、cat の完全上位互換なので既存の手癖を壊さず、1日使うと他ツールの cat 風出力が急に古く感じるようになる。これはシェル環境の上位互換ツールが成功した時の典型的なサインだ。

レバレッジが効くのは設定ファイル周りで、~/.config/bat/config に10分かけてテーマ・スタイル・--map-syntax を書いておくと、あとは意識から消える。MANPAGER と fzf の連携はそれぞれシェルRC に2行足すだけで毎日の作業体験が変わる、コスパ最強のボーナスだ。

bat がここまで速い理由が気になる人は Rust 製 CLI が爆速な理由 を、どの古典コマンドをどのモダンツールで置き換えるべきかの対応表が欲しい人は CLI ツール対応マップ を参照してほしい。シェル設定をゼロから整えるフェーズなら、この記事の設定スニペットを dotfiles と環境構築ガイド に集約しておくと、マシンを乗り換えても一瞬で同じ環境が再現できる。