「エラーメッセージだけを別のファイルに残したい」
Linuxを触り始めた人が、最初にぶつかる壁がこれです。
この記事では、Linuxのリダイレクトとパイプについて、完全初心者向けに手順と実行例で解説します。
ターミナルの使い方に少し慣れてきた段階で読むと、コマンドの世界が一気に広がります。
Ubuntu 24.04 LTS / Rocky Linux 9 / WSL2環境で動作確認済みです。
この記事のポイント
・リダイレクト「>」でコマンドの結果をファイルに保存できる
・パイプ「|」で前のコマンドの出力を次のコマンドに渡せる
・「2>」でエラーだけ、「&>」「2>&1」で出力をまとめてファイルに書ける
・xargsを使うとパイプ結果をコマンドの引数として扱える
・ヒアドキュメント「<<EOF」でスクリプト内に複数行テキストを書ける
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
なぜリダイレクトとパイプを覚えるのか?(背景・原理)
Linuxのコマンドは、ひとつひとつが小さな道具です。ひとつで完結するものは少なく、つなげて使うことで本来の力を発揮します。
そのつなぎ役がリダイレクトとパイプです。
リダイレクトは「コマンドの出力先をファイルに切り替える」機能、パイプは「前のコマンドの出力を次のコマンドに渡す」機能です。
この2つを理解すると、次のようなことが1行でできるようになります。
・ディレクトリ一覧をテキストファイルに保存する
・ログから特定のキーワードを含む行だけ取り出す
・エラーメッセージだけを別ファイルに記録する
・コマンド結果を画面で見つつ、同時にファイルにも残す
コピペや手作業で頑張っていた作業が、一気に自動化の入り口に変わります。
WindowsでいうとエクスプローラーやExcelで人手でやっていたファイル操作・集計が、1行のコマンドで自動化できるイメージです。
Linuxには「標準入力(stdin)」「標準出力(stdout)」「標準エラー出力(stderr)」という3本の流れ(ストリーム)があり、リダイレクトとパイプはこれらを切り回す仕組みです。
OSの内部では、それぞれにファイルディスクリプタ番号が割り振られています。
・標準入力(0 / stdin):コマンドへのデータの流れ込み口(キーボード入力など)
・標準出力(1 / stdout):正常な結果の出口(通常はターミナル画面)
・標準エラー出力(2 / stderr):エラーメッセージ専用の出口(同じく画面)
この番号が「2>」や「2>&1」のような構文の「2」に直結しています。
「2>」は「ファイルディスクリプタ2(stderr)をファイルへ向け直す」という意味です。
記号の意味をこう理解しておくと、応用構文を見たときに「なぜそう書くのか」が腑に落ちやすくなります。
リダイレクトはこの出口をファイルに切り替え、パイプは出口を次のコマンドの入口につなぎます。
まずはリダイレクト「>」で結果をファイルに保存する
リダイレクトは「出力先を切り替える」機能です。普段、コマンドの結果は画面(ターミナル)に表示されますが、これをファイルに向け直せます。
1. ls の結果をファイルに書き出す
ホームディレクトリの一覧を、file.txtというファイルに保存してみます。# カレントディレクトリの一覧をファイルに保存 $ ls > file.txt # 中身を確認 $ cat file.txt Desktop Documents Downloads Pictures file.txt
画面には何も表示されません。これで正常です。
リダイレクト先のファイルが存在しない場合は自動で新規作成されるので、touchで先に作る必要はありません。
2. 上書きと追記の違いを覚える
ここが初心者のつまずきポイントです。・>(上書き):毎回ファイルを空にしてから書き込む
・>>(追記):既存の中身は残したまま末尾に書き足す
# 上書き(以前のfile.txtの内容は消える) $ date > file.txt $ cat file.txt Mon May 4 12:30:01 JST 2026 # 追記(前の内容の下に日時が追加される) $ date >> file.txt $ cat file.txt Mon May 4 12:30:01 JST 2026 Mon May 4 12:30:15 JST 2026
一度実行するとファイルの中身は戻ってこないので注意してください。
ログのように「履歴を残したい」用途では必ず「>>」を使うクセをつけてください。
なお、上書き事故を防ぐシェルオプションとして「noclobber」があります。
設定しておくと「>」での既存ファイル上書きをシェルがエラーにしてくれます。
# noclobberを有効にする $ set -C # 既存ファイルへの上書きリダイレクトがエラーになる $ date > file.txt bash: file.txt: cannot overwrite existing file # 強制上書きしたいときは |> を使う(noclobber無効化上書き) $ date |> file.txt # noclobberを解除する $ set +C
3. エラーメッセージだけをファイルに分ける
先ほど説明した標準出力(1)と標準エラー出力(2)を使い分けます。「2>」を使うと、エラー(標準エラー出力)だけを別のファイルに書き出せます。
# 存在しないファイルをlsした場合 $ ls /not_exist_dir 2> error.log # error.logにエラーだけ記録される $ cat error.log ls: cannot access '/not_exist_dir': No such file or directory
# 正常出力もエラーも all.log に全部入れる(bash拡張構文) $ ls /etc /not_exist_dir &> all.log # 中身を確認すると、正常出力とエラーが混ざって記録されている $ cat all.log ls: cannot access '/not_exist_dir': No such file or directory /etc: NetworkManager bash.bashrc hosts (以下省略)
cronスクリプトのログ記録でよく使うパターンなので、どちらの書き方も覚えておくと後で必ず助かります。
4. ヒアドキュメント(<<EOF)で複数行テキストをコマンドに渡す
「<<」は「ここに書いた複数行テキストをコマンドの標準入力に渡す」機能です。ヒアドキュメント(here-document)と呼ばれ、スクリプト内でファイルを外から用意せずに複数行を入力したいときに使います。
# catでヒアドキュメントをファイルに書き出す $ cat > /etc/motd << EOF Welcome to my server. Please read the rules before proceeding. EOF # シェルスクリプト内でsshに複数コマンドをまとめて渡す $ ssh user@remote-server << EOF sudo systemctl restart nginx sudo systemctl status nginx EOF
変数展開を防ぎたい場合は先頭に「'」を付けて「<<'EOF'」と書きます。
1行だけ渡す場合は「<<<」(ヒアストリング)も便利です。
# 1行の文字列をbase64に渡す $ base64 <<< "hello world" aGVsbG8gd29ybGQK # grepに文字列を渡して判定する(パイプのecho代替) $ grep -q "root" <<< "root:x:0:0:root:/root:/bin/bash" && echo "found" found
現場でスクリプトを書くときに覚えておくと、コードがすっきりします。
パイプ「|」でコマンドをつなげる
パイプは「前のコマンドの結果を、次のコマンドの入力に渡す」機能です。記号は縦棒「|」。日本語キーボードでは Shift + ¥(円マーク)で入力します。
1. ファイル一覧を less で1画面ずつ見る
/etcディレクトリのように、ファイル数が多すぎて画面からあふれてしまう場合があります。そのままlsするとスクロールが追いつきません。
# lsの結果をlessに渡して、1画面ずつ表示する $ ls /etc | less
パイプで渡せば、どんなコマンドの結果にも使えます。
2. grep と組み合わせて「必要な行だけ」抜き出す
パイプの真価が出るのがgrepとの組み合わせです。grepは「指定した文字を含む行だけを表示する」コマンドです。
# 起動中のプロセスから「nginx」を含む行だけ表示 $ ps aux | grep nginx nginx 1234 0.0 0.5 56432 5120 ? S 10:00 0:00 nginx: master process nginx 1235 0.0 0.3 56988 3072 ? S 10:00 0:00 nginx: worker process # /etc配下のファイルからconfを含むファイル名だけ表示 $ ls /etc | grep conf resolv.conf nsswitch.conf sysctl.conf # -v オプションで「含まない行」だけ表示(grep自身を除外する定番パターン) $ ps aux | grep nginx | grep -v grep nginx 1234 0.0 0.5 56432 5120 ? S 10:00 0:00 nginx: master process nginx 1235 0.0 0.3 56988 3072 ? S 10:00 0:00 nginx: worker process
「grep -v grep」を追加してgrepプロセスを除外するのが現場の定番パターンです。
これを覚えるだけで、ログ調査や設定ファイル探しのスピードが段違いになります。
3. wc -l で行数を数える
パイプは何段でもつなげられます。# /etc配下のファイル数を数える $ ls /etc | wc -l 214 # ログの中で「error」を含む行数を数える $ cat /var/log/syslog | grep error | wc -l 17 # 起動中のnginxワーカープロセス数を数える $ ps aux | grep nginx | grep -v grep | wc -l 2
1つのコマンドで全部やろうとせず、それぞれ得意なコマンドを直列につなぐのが正解です。
4. sort と uniq で「集計」する
ログから「同じ単語が何回出ているか」を数えるのも、パイプの定番パターンです。# アクセスログから接続元IPを上位5件抽出 $ awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -5 1043 192.168.1.10 827 192.168.1.22 415 192.168.1.30 198 192.168.1.55 47 192.168.1.78
小さなコマンドを5段つないだだけで、立派な集計ツールになります。
障害調査でアクセス集中元を探すとき、このワンライナーは本当によく使います。
5. xargs でパイプ結果をコマンドの「引数」に変換する
パイプは「標準入力」にデータを渡しますが、コマンドによっては引数でしかデータを受け取れないものがあります。そういうときに使うのがxargsです。
# findで見つけたファイルをxargsでrmに渡す(30日以上前の.tmpファイルを一括削除) $ find /tmp -name "*.tmp" -mtime +30 | xargs rm -f # grepで見つかったファイルにchmodを一括適用 $ find /home/user/scripts -name "*.sh" | xargs chmod +x # ファイルの中身(URL一覧)を1行ずつcurlに渡す $ cat url_list.txt | xargs -I{} curl -s {} -o /dev/null -w "%{http_code}\n"
ファイル名にスペースが含まれる場合は「xargs -d '\n'」や「xargs -0」(null区切り)を組み合わせると安全です。
一括処理の場面でパイプとxargsの組み合わせは定番になるので、頭の片隅に置いておくと便利です。
応用・実務Tips
1. リダイレクトとパイプを組み合わせる
ここまで来たら、両方を一緒に使えます。# syslogからerrorを含む行を抽出して、result.txtに保存 $ cat /var/log/syslog | grep error > result.txt # psの結果から特定プロセスを抜き出して追記保存 $ ps aux | grep nginx >> nginx_check.log # 直近1時間のエラーをカウントしてログに追記 $ awk -v since="$(date -d '1 hour ago' '+%Y-%m-%dT%H')" '$0 ~ since' /var/log/syslog | grep -i error | wc -l >> /var/log/hourly_error_count.log
調査系の作業はほぼこの形で済むと言ってもいいくらいです。
2. tee で「画面表示しつつファイルにも保存」する
パイプで結果をファイルに送ると、画面には何も出なくなります。「画面でも確認したいし、同時にファイルにも残したい」というときはteeコマンドが便利です。
# 画面表示と同時にlog.txtにも書き込む $ ls /etc | tee log.txt NetworkManager bash.bashrc hosts (以下省略) # -aオプションで追記モード $ date | tee -a log.txt # パイプの途中で挟んでデバッグに使う $ cat /var/log/syslog | grep error | tee /tmp/errors.txt | wc -l
パイプの途中に tee を挟むと「ここまでの中間結果を保存しつつ次の処理に渡す」デバッグ技としても使えます。
3. /dev/null で「いらない出力を捨てる」
エラー出力が多くて邪魔なときは「2> /dev/null」で捨ててしまえます。/dev/null は何を入れても消えるLinux特有の「ブラックホール」です。
# findで権限エラー(Permission denied)が大量に出るのを抑制 $ find / -name "*.conf" 2> /dev/null # 正常出力もエラーも全て捨てる(cron等で結果を見ない場合) $ some_command > /dev/null 2>&1
意味は「標準出力(1)を/dev/nullへ → さらに標準エラー出力(2)を標準出力(1)と同じ場所へ転送」。
2つの記述順序に注意が必要で、「2>&1 > /dev/null」と逆に書くとエラーだけ残る挙動になります。
4. cronスクリプトでのログ記録パターン
cronで自動実行するスクリプトは、実行結果をファイルに残しておかないと「動いたかどうか」がわかりません。現場でよく使う3パターンを整理します。
# パターン1: 正常出力だけログに残す(エラーは捨てる) 0 2 * * * /home/user/scripts/backup.sh > /var/log/backup.log 2>/dev/null # パターン2: 正常・エラー両方をログに残す(最も一般的) 0 2 * * * /home/user/scripts/backup.sh >> /var/log/backup.log 2>&1 # パターン3: 完全サイレント(ログも通知も不要な場合のみ) 0 2 * * * /home/user/scripts/cleanup.sh > /dev/null 2>&1
毎回上書きではなく追記にする理由は、前回の実行ログが消えてしまうと原因調査ができなくなるからです。
また、crontabのバックアップ自体もリダイレクトで一発でできます。
# 現在のcrontabをファイルに保存(バックアップ) $ crontab -l > ~/crontab_backup.txt # 保存したバックアップを確認 $ cat ~/crontab_backup.txt
5. AIツールと組み合わせて学習を加速する
リダイレクトとパイプは、組み合わせ次第で無数のパターンが生まれます。最初は「こういうときどう書くの?」と迷いますが、ここでAIツールが役に立ちます。
ChatGPTやGitHub Copilotに、次のように聞いてみてください。
・「/var/log/syslog からerrorかwarnを含む行を抽出してcount.txtに保存するコマンドを教えて」
・「lsの結果を日付順に並べて上位10件だけ取り出すワンライナーを教えて」
提案されたコマンドを、意味を確認しながら自分の手で打ってみる。
この往復を繰り返すと、パイプとリダイレクトの感覚が短期間で身につきます。
大事なのは、丸暗記ではなく「つなげる発想」を持つことです。
「Permission denied」「Broken pipe」が出た時の対処法
1. 「Permission denied」でファイルに書けない
書き込み権限のないディレクトリ(/etcなど)にリダイレクトするとこのエラーになります。ホームディレクトリ配下に書き出すか、管理用途であればsudoを使います。
# これはエラーになる $ ls > /etc/mylist.txt bash: /etc/mylist.txt: Permission denied # ホーム配下に書き出せばOK $ ls > ~/mylist.txt
2. 「sudo echo xxx > ファイル」が書けない
これも初心者が必ずハマるパターンです。sudoは「echo」には効きますが「>」はシェル側の処理なので、権限が引き継がれません。
teeコマンドを使うのが定番の解決策です。
# NG: リダイレクトの部分に権限がない $ sudo echo "test" > /etc/test.conf bash: /etc/test.conf: Permission denied # OK: teeを使うとsudo配下でファイルに書ける $ echo "test" | sudo tee /etc/test.conf test # 既存ファイルに追記したいときは tee -a $ echo "additional line" | sudo tee -a /etc/test.conf
3. パイプでつないでも結果が出ない
grepで何も出ない場合は、大文字小文字の違いを疑います。「-i」で無視できます。# 大文字小文字を区別すると一致しない $ cat app.log | grep error (何も表示されない) # -iで大文字小文字を無視するとマッチする $ cat app.log | grep -i error 2026-05-04 10:21:33 [ERROR] connection refused 2026-05-04 10:25:18 [Error] timeout
4. 「Broken pipe」が出る
パイプの後段(受け側)が早く終了した場合に「Broken pipe」エラーが出ることがあります。代表例は head との組み合わせです。
# 大量のログをheadで先頭10行だけ取り出す(残りは破棄) $ cat huge.log | head (10行表示) cat: write error: Broken pipe # エラー出力を捨てれば見た目はきれいになる $ cat huge.log 2> /dev/null | head
動作には影響しないので、見た目が気になるなら 2> /dev/null で抑えれば十分です。
5. パイプ後にシェル変数が反映されない
実務でハマりやすい落とし穴がもうひとつあります。パイプの後段はサブシェル(子プロセス)で動くため、そこで変数に代入しても親シェルに反映されません。
# NG: パイプ後のwhileループ内で変数に加算してもループ外で0のまま $ count=0 $ cat numbers.txt | while read n; do count=$((count + n)); done $ echo $count 0 ← 期待した合計が反映されない! # OK: プロセス置換 <() でサブシェル回避 $ count=0 $ while read n; do count=$((count + n)); done < numbers.txt $ echo $count 55 ← 正しく合計される
パイプの代わりに「<( )」(プロセス置換)かリダイレクトでファイルを渡す書き方に切り替えると解決します。
本記事のまとめ
| やりたいこと | コマンド |
|---|---|
| 結果をファイルに保存(上書き) | ls > file.txt |
| 結果をファイルに追記 | date >> file.txt |
| エラーだけ別ファイルに保存 | ls /not_exist 2> error.log |
| 正常もエラーもまとめて保存 | ls /etc /not_exist &> all.log |
| 正常もエラーも追記保存(sh互換) | script.sh >> out.log 2>&1 |
| 上書き事故を防ぐ | set -C |
| 複数行をコマンドに渡す | cat > file.txt << EOF ... EOF |
| コマンドをつないで絞り込む | ps aux | grep nginx |
| 結果を1画面ずつ見る | ls /etc | less |
| 行数を数える | cat app.log | grep error | wc -l |
| 画面表示しつつファイル保存 | ls /etc | tee log.txt |
| 不要な出力を捨てる | find / -name "*.conf" 2> /dev/null |
| sudo配下でファイルに書く | echo "test" | sudo tee /etc/test.conf |
| パイプ結果をコマンド引数に渡す | find /tmp -name "*.tmp" | xargs rm -f |
| crontabをバックアップする | crontab -l > ~/crontab_backup.txt |
最初は記号が多くて戸惑いますが、毎日触っていれば1週間で体に馴染みます。
「画面に出すか、ファイルに送るか」「次のコマンドに渡すか」を意識するだけで、作業効率は10倍変わります。
次に学ぶべき関連記事
リダイレクトとパイプを覚えたら、実務でよく使うコマンドと組み合わせて練習しましょう。以下の記事はどれも、この記事と同じ考え方で理解できるはずです。
・ポート確認(ss / lsof)の使い方
・DNS設定 resolv.conf と nmcli の使い方
・tarコマンドで圧縮・解凍する方法
・mountとfstabでディスクをマウントする方法
・Postfixのバージョンを確認する方法
・chkconfigとsystemctlでサービスを管理する方法
・ftpコマンドで複数ファイルをまとめて転送する方法
無料の「Linuxサーバー構築入門マニュアル(図解60ページ)」をプレゼントしています。
コマンド学習の先にある「サーバーをゼロから組み立てる力」を、初心者が迷わない順序で学べる一冊です。
無料マニュアルを受け取る >>
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
登録10秒/合わなければ解除3秒 / 詳細はこちら
- 次のページへ:Linuxのネットワーク確認入門|ipコマンドとpingで接続状態を調べる方法
- 前のページへ:Linuxのプロセス入門|バックグラウンド・フォアグラウンドの違いとps・pgrepでの確認方法
- この記事の属するカテゴリ:【Linux入門】初心者のための基礎知識・講座へ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は1分、解除もいつでも可。
登録無料・いつでも解除できます