【Shell】リダイレクトを使用したファイル入出力操作:「標準入力」・「標準出力」・「標準エラー出力」を操作する

■標準入出力

標準入出力とは、linuxコマンドの入力、コマンド実行結果の出力、コマンド実行時のエラー出力の3つを示す。
この3つをそれぞれ、「標準入力」・「標準出力」・「標準エラー出力」と呼ぶ。
下表に標準入出力の概要を示す。

標準入出力概要ファイルディスクリプタの番号
標準入力コマンドの入力、実行0
標準出力コマンド実行結果の表示1
標準エラー出力コマンド実行時のエラー表示2
表_標準入出力一覧
※ファイルディスクリプタの番号については後述にて説明

▼ざっくりイメージ

図_標準入出力ざっくりイメージ

■リダイレクト

linuxコマンドを実行するとき、標準入力の入力先、標準出力・標準エラー出力の出力先を変更する機能をリダイレクトと呼ぶ。
出力先をテキストファイルなどに変更することで、ログ管理としても役立つ。

▼リダイレクトコマンドの一覧

下表にリダイレクトコマンドの一覧を示す。

コマンド概要
< file標準入力をファイルに変更
> file標準出力をファイルに変更
>> file標準出力をファイルの末尾に追記
>| filenoclobberの上書き無効設定を無視して標準出力をファイルに変更
2> file標準エラー出力をファイルに変更
2>> file標準エラー出力をファイル末尾に追記
2>| filenoclobberの上書き無効設定を無視して標準エラー出力をファイルに変更
n>&mファイルディスクリプタn番をファイルディスクリプタm番にコピー
2>&1で標準出力・標準エラー出力を同じファイルに追記
&>>標準出力および標準エラー出力を一つのファイルに出力(追記)
> /dev/null読み込んでもデータはない。
書き込んでも書き込まれることはない。
(不要な出力を省ける)
表_リダイレクトコマンド一覧

また、それぞれのリダイレクトコマンドについて、使い方を示す。

・標準入力をファイルに変更(< file)

既存のファイルをインプットとして、コマンドを実行する場合に使用する。

# ファイルの中身を表示する
$ cat hoge.txt
america
apple
aaa

# 小文字の[a]を大文字[A]に変更する 
$ tr a A < hoge.txt
AmericA
Apple
AAA

# ファイルディスクリプタ番号(0)を指定する:省略可能
$ tr a A 0< hoge.txt
AmericA
Apple
AAA

ファイルディスクリプタ番号(0)を指定し、リダイレクトを「 0< 」で実行しても結果は同じである。
なお、ファイルディスクリプタ番号(0)は省略可能。

・標準出力をファイルに変更(> file)

コマンドの実行結果をファイルに出力する。

$ echo Hello World! > a.txt
$ cat a.txt
Hello World!

$ echo Hello Japan! > a.txt
$ cat a.txt
Hello Japan!

# ファイルディスクリプタ番号(1)を指定する:省略可能
$ echo Hello Tokyo! 1> a.txt
$ cat a.txt
Hello Tokyo!

リダイレクトコマンド「 > 」では上書きするため、出力結果は書き換えられる。

ファイルディスクリプタ番号(1)を指定し、リダイレクトを「 1> 」で実行しても結果は同じである。
なお、ファイルディスクリプタ番号(1)は省略可能。

・標準出力をファイルの末尾に追記(>> file)

コマンドの実行結果をファイルに追記する。

$ echo Hello World! >> b.txt
$ cat b.txt
Hello World!

$ echo Hello Japan! >> b.txt
$ cat b.txt
Hello World!
Hello Japan!

# ファイルディスクリプタ番号(1)を指定する:省略可能
$ echo Hello Tokyo! 1>> b.txt
$ cat b.txt
Hello World!
Hello Japan!
Hello Tokyo!

リダイレクトコマンド「 >> 」では追記するため、出力結果は蓄積される。

・上書き無効設定を無視して標準出力をファイルに変更(>| file)

noclobberの上書き無効設定を無視してファイルに出力する。

# 上書き無効
$ set -o noclobber
$ echo Hello World! > c.txt
$ echo Hello AAA! > c.txt
-bash: c.txt: 存在するファイルを上書きできません

$ cat c.txt
Hello World!

$ echo Hello AAA! >| c.txt
$ cat c.txt
Hello AAA!

#上書き無効解除
set +o noclobber

・標準エラー出力をファイルに変更(2> file)

標準エラー出力をファイルに変更するときは、ファイルディスクリプタの番号「2」を指定する。

# 階層あり(ファイル出力内容は空)
$ ls /work 2> err.txt
err.txt  hoge.txt

標準出力はファイル出力に変更していないため、コンソール上に表示される。
また「err.txt」の中身は空である。


# 階層なし(ファイル出力内容はエラー内容)
$ ls /work/xxx 2> err.txt
$ cat err.txt
ls: /work/xxx にアクセスできません: そのようなファイルやディレクトリはありません

「err.txt」に「ls」コマンドの実行エラー内容が記載されている。


$ ls /work > result.txt 2> error.txt
$ cat result.txt
result.txt error.txt

$ ls /work/xxx > result.txt 2> error.txt
$ cat error.txt
ls: /work/xxx にアクセスできません: そのようなファイルやディレクトリはありません

標準出力と標準エラー出力を分けることもできる。

・標準エラー出力をファイル末尾に追記(2>> file)

標準エラー出力をファイル末尾に追記する場合は、標準出力と同様に、「>>」を使用する。
また、ファイルディスクリプタの番号「2」を指定する。

$ ls /work/aaa 2>> errA.txt
$ ls /work/bbb 2>> errA.txt
$ cat errA.txt
ls: /work/aaa にアクセスできません: そのようなファイルやディレクトリはありません
ls: /work/bbb にアクセスできません: そのようなファイルやディレクトリはありません

・上書き無効設定を無視して標準エラー出力をファイルに変更(2>| file)

noclobberの上書き無効設定を無視してファイルに標準出力エラーを出力する。

# 上書き設定無効
$ set -o noclobber
$ ls /work/abc 2> errB.txt
$ ls /work/efg 2> errB.txt
-bash: errB.txt: 存在するファイルを上書きできません

# 上書きされていないため1回目のls実行結果が出力
$ cat errB.txt
ls: /work/abc にアクセスできません: そのようなファイルやディレクトリはありません

# 強制的に上書き
$ ls /work/efg 2>| errB.txt
$ cat errB.txt
ls: /work/efg にアクセスできません: そのようなファイルやディレクトリはありません

#上書き無効解除
$ set +o noclobber

・標準出力、標準エラー出力を同じファイルに追記(2>&1)(&>>)

標準出力と標準エラー出力を同じファイルに追記させる方法は、標準エラー出力のリダイレクトコマンド「2>」の後ろに「&1」を指定する。

# 正常系実行
$ ls /work >> log.txt 2>&1
# 異常系実行
$ ls /work/xxx >> log.txt 2>&1

$ cat log.txt
log.txt
ls: /work/xxx にアクセスできません: そのようなファイルやディレクトリはありません

「&>>」で実行しても標準出力と標準エラー出力を同じファイルに追記させることができる。

# 正常系実行
$ ls /work &>> log2.txt
# 異常系実行
$ ls /work/xxx &>> log2.txt

$ cat log2.txt
log2.txt
ls: /work/xxx にアクセスできません: そのようなファイルやディレクトリはありません

・不要な出力を省略(> /dev/null)

linux環境には、「/dev」ディレクトリに「null」ファイルが配置されている。

/dev/null には以下の特性がある。

①/dev/nullから読み込んでも何もデータは返されない。
②/dev/nullにデータを書き込んでも反映されない。

リダイレクト先を/dev/nullを使用する利点としては、メッセージ出力を省略することができる。

# 何も表示されない
$ cat /dev/null

# 標準出力しても反映されない
$ ls /work &>> /dev/null
$ cat /dev/null

# 標準エラー出力しても反映されない
$ ls /work/xxx &>> /dev/null
$ cat /dev/null

タイトルとURLをコピーしました