Linux: 標準出力とリダイレクト

terminal出力結果をコントロールする

公開日: 2023-05-02
更新日: 2024-03-04

  Table of Contents

はじめに: 標準入出力とリダイレクトの関係

コンピューターの世界には, データの「入力」と「出力」という流れ(=Data Streams)があります. 特に, キーボードからの入力を標準入力, ディスプレイへの出力を標準出力と呼びます.

多くのコマンドは, 何も指定しなくても実行結果をディスプレイに表示しますが, これは標準出力としてディスプレイを使うことが デフォルトとして設定されているためです.

一方, この標準出入力先を変更する機能のことをリダイレクトといいます. 標準出入力とリダイレクトを理解することで, コマンドがなにを出力するのかをコントロールできます.

標準出入力

Def: stdin, stdout, stderr

標準入力 standard input, stdin コマンドが標準的に利用するデータ入力元, 通常はキーボード
標準出力 standard output, stdout コマンドが標準的に利用するデータ出力先, 通常はディスプレイ
標準エラー出力 standard error, stderr コマンドのエラーメッセージは, 通常の出力とは区別されるが, 通常は標準出力同様にディスプレイ

トラブルが起きてエラー出力を行う必要がある場合に, 標準エラー出力(=stderr)というものがあります. 通常, 標準エラー出力はディスプレイになりますが, 後に説明するリダイレクトを使用することで, ファイルに出力する使い方もあります.

ファイル記述子

全てのプロセスはファイルディスクリプタ (fd: file descriptor, ファイル記述子)というファイル書き込み用の通信チャネルを持っています.

入出力チャネル ファイル記述子
標準入力 0
標準出力 1
標準エラー 2

リダイレクトとパイプ

リダイレクト

リダイレクトの代表例

< FileA 標準入力をFileAに変更
> FileA 標準出力をFileAに変更
>> FileA 標準出力をFileAの末尾に追記
2> FileA 標準エラー出力をFileAに変更
2>> FileA 標準エラー出力をFileAの末尾に追記
> FileA 2>&1 標準出力と標準エラー出力をまとめてFileAに変更
&> FileA 標準出力と標準エラー出力をまとめてFileAに変更
>& FileA 標準出力と標準エラー出力をまとめてFileAに変更

ファイル記述子を組み合わせることでリダイレクト対象を制御することができます. 例えば, lsの標準出力結果を fileAへ新規に書き込む場合, ファイル記述子を利用するパターンと利用しないパターンで以下のように書くことができます

1
2
3
4
5
## リダイレクトのみ
% ls > fileA

## ファイル記述子を利用
% ls 1> fileA

FileAの内容を並び替えて, その結果を別のファイルFileBに保存する場合

1
% sort < FileA > FileB

構文まとめ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
## CMD標準出力結果をfileAへ格納
% CMD > fileA
% CMD 1> fileA

## CMD標準出力結果をfileAへ追記する
% CMD >> fileA
% CMD 1>> fileA

## lsコマンドを実行して標準エラー出力結果(non-exist-file)のみをfileAに格納する
% ls exist-file non-exist-file 2> fileA

## lsコマンドを実行して標準出力及びエラー出力結果両方をfileAに格納する
% ls exist-file non-exist-file &> fileA
% ls exist-file non-exist-file >& fileA
% ls exist-file non-exist-file 1> fileA 2>&1
% ls > fileA exist-file non-exist-file 2>&1

## 標準出力と標準エラーのリダイレクト先を分けるとき
% CMD 1> result.txt 2> error.txt

パイプ

Def: パイプ

コマンド日よって得られた結果を別コマンドに引き渡す機能のことをパイプと呼ぶ.

CMD1の実行結果をCMD2の標準入力に渡す場合,

1
% CMD1 | CMD2

標準出力と標準エラー出力をまとめてパイプで渡したい場合は, 2>&1 |, または |& を用います. sedコマンドに引数を渡さずに実行すると, 標準エラー出力として使用方法が出てきますが, そのラインをカウントしたい場合は

1
2
3
4
5
## 標準エラー出力用のパイプ
% sed |& wc -l

## ファイル記述子とパイプの組み合わせ
% sed 2>&1 | wc -l

Tips: 実務で役に立つ事例集

エラーメッセージを出力しない

エラーメッセージをterminalへ出力したくない場合は 2> /dev/null で標準エラーメッセージを /dev/nullへリダイレクトします.

Def: 疑似ファイルデバイスとしての/dev/null

Linux系OSでは /dev/null という疑似デバイスファイルを用意してある. /dev/null に書き込まれたデータはすべて破棄され, どこからどれだけ読み込んでも何もデータを返さない.

標準出力と標準エラー出力両方を出力させない場合は以下のようにリダイレクトを用います

1
2
3
4
## 標準出力と標準エラー出力両方を出力させない場合
% echo 'stderr' >& /dev/null
% echo 'stderr' &> /dev/null
% echo 'stderr' > /dev/null 2>&1

エラーメッセージのみ出力させたくない場合は

1
% echo 'stderr' 2> /dev/null

エラーメッセージのみ出力させる場合

  • 標準出力結果を/dev/nullへ捨てる
  • 標準エラー出力を標準出力へ渡す

という形で実行します

1
2
3
4
5
## CMD1のエラー出力のみをCMD2へ渡す
% (CMD1 > /dev/null) |& CMD2

## CMD1のエラーを標準出力, 標準出力を/dev/nullに捨てる場合
% (CMD1 2>&1 1> /dev/null) | CMD2

注意点として, 2つ目の例と似てるけれども違う挙動してしまうのが

1
% (CMD1 1> /dev/null 2>&1 ) | CMD2

これは先に標準出力先が先に/dev/nullとなり, 標準エラーが標準出力の順番なのですべてが/dev/nullに捨てられてしまう設定になります.

例: poetryで標準エラー出力のみを出力する場合

poetryコマンドを用いるときなど, 標準出力結果には興味がないがエラーだけ知りたいという場合があります. この場合は

1
2
3
% poetry update 1> /dev/null
% poetry update > /dev/null
% poetry update 2>&1 1> /dev/null

どちらも標準出力結果を/dev/nullに捨てる一方, 標準エラーはちゃんと端末に出力されます.

ファイルへの書き込みと標準出力を同時に行う: teeコマンド

Def: teeコマンド

  • teeコマンドは, 標準入力から読み込んだデータを標準出力とファイルの両方に出力するコマンド
1
% tee [option] file_name

-aオプションを加えることでファイルに追記することができる.

/etc/passwdファイルの内容に行番号を付け, その結果をパイプを通してファイルへ出力し, さらにその結果をパイプでheadコマンドに渡したいとします.

1
2
3
4
5
6
7
8
9
10
% nl /etc/passwd | tee test.txt | head -3
     1	root:x:0:0:root:/root:/usr/bin/zsh
     2	daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
     3	bin:x:2:2:bin:/bin:/usr/sbin/nologin
% cat test.txt
     1	root:x:0:0:root:/root:/usr/bin/zsh
     2	daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
     3	bin:x:2:2:bin:/bin:/usr/sbin/nologin
    ...
    50	vboxadd:x:495:1::/var/run/vboxadd:/bin/false

References



Share Buttons
Share on:

Feature Tags
Leave a Comment
(注意:GitHub Accountが必要となります)