catコマンド 使い方:ファイル内容の表示と結合

概要

catコマンドはファイルの内容を標準出力に表示し、複数ファイルの結合(concatenate)を行うLinux/Unix標準コマンドです。

現場では設定ファイルの確認、ログの即座の確認、複数ファイルの結合、ヒアドキュメントによるファイル生成など、日常的な運用タスクで最も多用されます。このコマンドを使いこなせないと、単純な確認作業にも無駄な手順を踏むことになり、トラブルシューティングの初動が遅れます。パイプやリダイレクトと組み合わせることで、高度なテキスト処理の起点となります。

基本コマンド・構文

ファイル内容の表示

cat /etc/hostname

実行結果:

$ cat /etc/hostname
web-server-01

複数ファイルの連結表示

cat file1.txt file2.txt

実行結果:

# file1.txtの内容
This is file 1.
# file2.txtの内容
This is file 2.

標準入力からの読み込み(ヒアドキュメント)

cat > newfile.txt << EOF
line 1
line 2
line 3
EOF

実行結果

# newfile.txtが作成され、3行のテキストが書き込まれる
# 標準出力には何も表示されない

ファイルへのリダイレクト

cat file1.txt file2.txt > combined.txt

実行結果:

# combined.txtに2つのファイルが結合されて保存される
# 標準出力には何も表示されない

現場で必須のオプション・設定

-n – 行番号付き表示

cat -n /var/log/application.log

実行結果:

     1  2024-01-15 10:23:45 INFO Application started
     2  2024-01-15 10:23:46 DEBUG Loading configuration
     3  2024-01-15 10:23:47 ERROR Connection timeout

実務での必要性:
ログファイルのエラー行を特定し、他のメンバーに「45行目のエラーを確認してください」と正確に伝えられます。grepsedと組み合わせた処理で、特定行の抽出・編集を行う際の基準となります。障害対応時のコミュニケーション効率が大幅に向上します。

-A – 不可視文字の可視化

cat -A config.yml

実行結果:

server:$
  host: localhost^I$
  port: 8080$

実務での必要性:
行末の改行($)、タブ文字(^I)、その他の制御文字を可視化します。YAMLやMakefileなど、空白文字に意味があるファイルのトラブルシューティングで必須です。「設定ファイルが正しいのにエラーになる」という問題の多くは、タブとスペースの混在や不要な行末スペースが原因であり、-Aで即座に発見できます。

-s – 連続する空行の圧縮

cat -s verbose-log.txt

実行結果:

Log entry 1

Log entry 2

Log entry 3

実務での必要性:
複数の連続する空行を1行にまとめます。冗長なログファイルやスタックトレースを画面表示する際、無駄なスクロールを減らし、重要な情報に素早くアクセスできます。cat -sgrepを組み合わせることで、可読性の高いログ抽出が可能です。

-v – 非表示文字の可視化(制御文字)

cat -v binary-mixed.txt

実行結果:

$ cat -v binary-mixed.txt
Normal text^M
More text^@^[

実務での必要性:
バイナリデータが混入したテキストファイルや、Windows形式のCRLF(^M)を検出します。異なるOS間でファイルを移動した際の文字コード問題、ログファイルへのバイナリ混入などを即座に特定できます。

-T – タブ文字の可視化

cat -T Makefile

実行結果:

$ cat -T Makefile
target:
^Icommand1
^Icommand2

実務での必要性:
タブ文字を^Iとして表示します。Makefileではタブとスペースの違いが構文エラーに直結するため、-Tによる確認は必須です。エディタの設定でタブが自動変換される環境では、このオプションでの事前確認が事故を防ぎます。

4. 実践的なユースケース(逆引きレシピ)

複数のログファイルを時系列順に結合

cat access.log.1 access.log.2 access.log.3 | sort | less

解説:
ローテーションされた複数のログファイルを結合し、時系列でソートして表示します。ログ調査の基本パターンです。lessでページング表示することで、大量のログも効率的に確認できます。

設定ファイルのバックアップと編集

cat /etc/nginx/nginx.conf > /etc/nginx/nginx.conf.bak.$(date +%Y%m%d)

解説:
設定ファイルを日付付きでバックアップします。cpコマンドでも可能ですが、catとリダイレクトの組み合わせは、パイプ処理で内容を加工しながらバックアップする応用が効きます。

コメント・空行を除いた設定ファイルの確認

cat /etc/ssh/sshd_config | grep -v '^#' | grep -v '^$'

実行結果:

$ cat /etc/ssh/sshd_config | grep -v '^#' | grep -v '^$'
Port 22
PermitRootLogin no
PasswordAuthentication yes

解説:
大量のコメント行を含む設定ファイルから、実際に有効な設定のみを抽出します。grep -v '^#'でコメント行を除外し、grep -v '^$'で空行を除外します。設定の全体像を素早く把握する定石です。

複数サーバーのホスト情報を一括収集

for host in web{01..03}; do
  echo "=== $host ===" 
  ssh $host "cat /etc/hostname && cat /proc/meminfo | grep MemTotal"
done > server-inventory.txt

解説:
複数サーバーにSSH接続し、ホスト名とメモリ情報を収集して1つのファイルにまとめます。インベントリ作成や定期的なサーバー情報収集の自動化に使用します。

ヒアドキュメントでスクリプト生成

cat > /tmp/backup.sh << 'EOF'
#!/bin/bash
DATE=$(date +%Y%m%d)
tar czf /backup/data-${DATE}.tar.gz /var/www/html
find /backup -name "*.tar.gz" -mtime +7 -delete
EOF
chmod +x /tmp/backup.sh

解説:
シェルスクリプトをその場で生成します。'EOF'とクォートすることで、変数展開を抑止できます。サーバー構築時の初期設定スクリプト作成や、一時的な運用スクリプトの生成に使用します。

エラーログの行番号付き抽出

cat -n /var/log/app.log | grep ERROR

実行結果:

$ cat -n /var/log/app.log | grep ERROR
    45  2024-01-15 10:23:47 ERROR Connection timeout
   128  2024-01-15 11:15:23 ERROR Database query failed

解説:
ログファイル全体に行番号を付与してからgrepでフィルタリングすることで、エラーが元のファイルの何行目にあるかを特定できます。vim +45 /var/log/app.logのように、特定行に直接ジャンプする際に有効です。

バイナリファイルの混入チェック

cat -v suspicious.txt | head -20

解説:
テキストファイルとして扱っているつもりが、バイナリデータが混入していないかを確認します。^@^[などの制御文字が表示されれば、ファイルの破損やエンコーディング問題を疑います。

5. シニアエンジニアの知恵(Expert Advice)

大きなファイルにはcatを使わない

# 悪い例: 数GBのログファイルを全表示
cat /var/log/huge.log

# 良い例: lessやheadを使う
less /var/log/huge.log
head -100 /var/log/huge.log
tail -100 /var/log/huge.log

理由:
catファイル全体を一度にメモリに読み込むわけではありませんが、標準出力への出力が完了するまで端末がブロックされます。数GBのファイルでは画面が延々とスクロールし続け、操作不能になります。ページング表示が必要な場合はless、先頭・末尾のみ確認する場合はhead/tailを使用してください。

catの無駄遣い(UUOC: Useless Use Of Cat)

# 非効率: catを経由する無駄なパイプ
cat file.txt | grep "error"

# 効率的: grepに直接ファイルを渡す
grep "error" file.txt

理由:
grepawksedなどのコマンドは、ファイル名を引数として受け取れます。わざわざcatでパイプする必要はなく、プロセスを1つ余分に起動するだけ無駄です。シェルスクリプトのレビューで最も指摘される非効率パターンの1つです。ただし、複数ファイルを結合してから処理する場合は、cat file1 file2 | grepが適切です。

リダイレクトの上書きリスク

# 危険: 元のファイルが空になる
cat file.txt | sed 's/old/new/' > file.txt

# 安全: 一時ファイルを経由
cat file.txt | sed 's/old/new/' > file.txt.tmp && mv file.txt.tmp file.txt

# より安全: sedの-iオプションを使う
sed -i.bak 's/old/new/' file.txt

理由:
シェルはリダイレクト(>)をコマンド実行前に処理するため、入力ファイルと出力ファイルが同じ場合、ファイルが空になってからコマンドが実行されます。必ず一時ファイルを経由するか、sed -iなどのインプレース編集機能を使用してください。

バイナリファイルへの誤使用

# 危険: バイナリファイルをcatすると端末が壊れる
cat /bin/ls

# 端末がおかしくなった場合の復旧
reset

理由:
バイナリファイルをcatすると、制御文字が端末に送信され、文字化けや表示崩れが発生します。最悪の場合、端末が応答しなくなります。resetコマンドで端末を初期化できますが、事前にfileコマンドでファイルタイプを確認する習慣をつけてください。

パイプの中間確認テクニック

# パイプ途中の結果を確認しながら処理
cat access.log | grep "POST" | tee /tmp/post-requests.txt | awk '{print $1}' | sort | uniq -c

理由:
teeコマンドを挟むことで、パイプの途中結果をファイルに保存しながら、後続の処理も継続できます。複雑なパイプ処理のデバッグや、中間結果を保存しておきたい場合に有効です。長大なパイプを一度に書かず、段階的に確認しながら構築できます。

ヒアドキュメントの変数展開制御

# 変数が展開される
cat > script.sh << EOF
echo "Current user: $USER"
EOF

# 変数が展開されない(リテラル)
cat > script.sh << 'EOF'
echo "Current user: $USER"
EOF

理由:
EOFをクォートしない場合、ヒアドキュメント内の変数はその場で展開されます。スクリプト生成時に実行時の変数を埋め込みたいのか、変数をそのまま記述したいのかを明確にし、適切にクォートを使い分けてください。この違いを理解していないと、意図しないスクリプトが生成されます。