Linuxのリダイレクトについて確認する

スポンサーリンク

シェルでは、実行するコマンドに対して'>'や'<'等のリダイレクト演算子を追加するとコマンドの入力元や出力先を変更することができます。

これをリダイレクトまたはリダイレクション(redirection)といいます。

例えば、'2&>1'は標準エラー出力を標準出力にコピーする意味でよく使用されます。

リダイレクトはコマンドを利用する上で知っておくべき重要な機能になります。

スポンサーリンク

リダイレクトの解釈

Bashの場合、リダイレクトの演算子は単純なコマンドの場合、コマンドの手前にあっても、コマンドの途中であっても、コマンドの後でも解釈されます。例えば、以下のコマンドの解釈はすべて同じ解釈になります。また、リダイレクトは左から順に解釈されていきます。

一般的にリダイレクトは、コマンドの最後に書かれることが多いです。

コマンド例と実行結果

 

 

 

ファイルディスクリプタを確認

リダイレクトの動作を確認する前に、ファイルディスクリプタ(ファイル記述子, file descriptor, fd)について少し確認します。カーネルがファイルを開くとき、全てのファイルをファイルディスクリプタで参照します。例えば、C言語でファイルを開くときも同様にファイルディスクリプタを使用します。

ファイルディスクリプタは非負の整数で表され、プロセスごとに管理されています。

現在のシェルでのファイルディスクリプタの状態(リダイレクトの状態)を確認する方法として、/dev/fdのディレクトリを確認する方法があります。

 

ファイルディスクリプタの0は標準入力1は標準出力2は標準エラー出力になります。また、9より大きいファイルディスクリプタはシェルが内部で使用する可能性があり、競合が起きるかもしれないため、使用する場合は注意が必要になります。

ここでのそれぞれのシンボリック先の/dev/pts/8は現在の端末を示します。例えば、ttyコマンドを用いると現在の端末のファイル名を表示できます。

 

/dev/fdは/proc/self/fdのシンボリックリンクになっています。

procファイルシステム(/procのディレクトリ)は、プロセスIDの数字のディレクトリでそれぞれのプロセスのプロセス情報を管理しています。/proc/selfは、procファイルシステム(/procのディレクトリ)で、/proc/selfを参照したプロセスと同じプロセスIDのプロセス情報にアクセスできます。

また、上のファイルディスクリプタの3のシンボリックリンク先/proc/3793/fdについてはここでは気にしません。もしここで、ファイルディスクリプタの3を使用した場合、別の影響のないファイルディスクリプタにシンボリックリンク先/proc/xxxx/fdのような表示が現れます。

 

 

 

execコマンドによるリダイレクトの設定の変更

組み込みコマンドのexecコマンドを用いると現在のシェルのリダイレクトの設定を変更することができます。

execコマンドは、コマンドを現在のシェルと置き換えて実行するコマンドになります。しかし、コマンドを入力せずにリダイレクトのみを入力すると現在のシェルでのリダイレクトの設定を変更できます。

コマンド例と実行結果

 

 

 

リダイレクトの動作を確認

入力のリダイレクト

入力のリダイレクト形式は以下のようになります。

[n]<word

nはファイルディスクリプタで、wordはファイル名を表します。nが省略された場合は、0(標準入力)が指定されます。

コマンド例と実行結果

 

 

 

出力のリダイレクト

出力のリダイレクトの形式は以下のようになります。

[n]>word

nはファイルディスクリプタで、wordはファイル名を表します。nが省略された場合は、1(標準出力)が指定されます。
また、指定したファイルが存在しない場合は作成されます。

コマンド例と実行結果

 

result.txt

 

また、組み込みコマンドのsetコマンドでnoclobberオプションがオンになっている場合は、既存のファイルに対して、'>'でファイルに上書きできず、'>|'を用いることで上書きできます。

 

setコマンドのオプションの状態の一覧は以下のコマンドで確認できます。
コマンド例

noclobberオプションをオンにする場合は以下のコマンドになります。
コマンド例

また、オフにする場合は以下のコマンドになります。
コマンド例

 

 

 

出力の追記

出力を追記する場合のリダイレクトの形式は以下のようになります。

[n]>>word

nはファイルディスクリプタで、wordはファイル名を表します。nが省略された場合は、1(標準出力)が指定されます。
また、指定したファイルが存在しない場合は作成されます。

コマンド例と実行結果

 

 

 

ファイルディスクリプタの複製

ファイルディスクリプタの複製の入力と出力の2つのパターンがあります。

入力の場合

入力の場合でのファイルディスクリプタの複製の形式は以下のようになります。

[n]<&word

nはファイルディスクリプタで、wordはファイルディスクリプタまたはファイル名を表します。wordが数字の場合はファイルディスクリプタとして扱い、それ以外は基本的に入力のリダイレクトとして扱います。

wordがファイルディスクリプタの場合、nはwordの複製になります。

nが省略された場合は、0(標準入力)が指定されます。

コマンド例と実行結果

 

 

 

出力の場合

出力の場合でのファイルディスクリプタの複製の形式は以下のようになります。

[n]>&word

nはファイルディスクリプタで、wordはファイルディスクリプタまたはファイル名を表します。wordが数字の場合はファイルディスクリプタとして扱い、それ以外は基本的に出力のリダイレクトとして扱います。

wordがファイルディスクリプタの場合、nはwordの複製になります。
よく使う例として、標準エラー出力を標準出力にする'2>&1'があります。

nが省略された場合は、1(標準出力)が指定されます。

コマンド例と実行結果

 

 

 

ファイルディスクリプタのクローズ

ファイルディスクリプタを閉じる場合、以下の形式を使用できます。

[n]<&-
[n]>&-

これは'[n]<&word'や'[n]>&word'のwordが'-'に解釈された場合になります。

どちらの場合も同じ意味でnのファイルディスクリプタを閉じます。

違いがあるのは、nが省略された場合、入力のリダイレクトのときは0(標準入力)に、出力のリダイレクトのときは1(標準出力)になります。

コマンド例と実行結果

 

 

 

ファイルディスクリプタの移動

以下の形式で、ファイルディスクリプタを移動することができます。

[n]<&digit-
[n]>&digit-

nとdigitはそれぞれファイルディスクリプタで、digitはnに移動します。

どちらの場合も同じ意味でnのファイルディスクリプタを移動します。

違いがあるのは、nが省略された場合、入力のリダイレクトのときは0(標準入力)に、出力のリダイレクトのときは1(標準出力)になります。

コマンド例と実行結果

 

 

 

ファイルディスクリプタを読み書き両方でオープン

ダイアモンド演算子(<>)を用いることでファイルディスクリプタを読み書きの両方で開くことができます。その形式は以下のようになります。

[n]<>word

nはファイルディスクリプタで、wordはファイル名を表します。

nが省略された場合は、0(標準入力)が指定されます。

ファイルの位置(file position)を意識することで、ファイルを読み込んだ後に、ファイルに書き込むことで途中の文字を変更することができます。

以下のコマンド例では、'Hello world!'と書き込まれたファイルに対して、ダイアモンド演算子によるリダイレクトを行い、最初に5文字読み込んだ後に、文字を書き込むことで、6文字目の文字を変更して、'Hello,world!'にしています。

コマンド例と実行結果

 

 

 

ヒアドキュメント

ヒアドキュメント(here documents)は以下の形式になります。

[n]<<[-]word
here-document
delimiter

nはファイルディスクリプタで、省略された場合は0(標準入力)になります。
ヒアドキュメントは指定したwordの文字列がdelimiterになり、delimiterとしてwordのみの文字列である行が表れるまで、here-documentである文字列を読み込みます。

wordでは、パラメータ展開・コマンド置換・算術展開・ファイル名展開などが行われません。

コマンド例と実行結果

 

'<<-'のリダイレクト演算子を用いるとhere-documentのすべての行の最初のタブ文字が取り除かれるため、タブ文字でインデントが行えます。

test.sh

 

コマンド例と実行結果

 

また、wordがすべて引用符に囲まれているかどうかで、here-documentの扱いが少し変わります。

引用符に囲まれていない場合

here-documentの行はすべてパラメータ展開・コマンド置換・算術展開が行われ、'\', '$', '`'の文字は、文字として出力する場合、'\'でエスケープする必要があります。

コマンド例と実行結果

 

 

 

引用符で囲まれている場合

delimiterはwordから引用符を取り除いた行になり、here-documentの行はパラメータ展開・コマンド置換・算術展開は行われません。

コマンド例と実行結果

 

 

 

ヒアストリング

ヒアストリング(here strings)は以下の形式になります。

[n]<<< word

nはファイルディスクリプタで、省略された場合は0(標準入力)になります。

ヒアストリングは最後に改行を加えた単一の文字列を入力として与えます。

wordはシェルによるパラメータ展開・コマンド置換・算術展開等や引用符の削除を行います。ただし、ファイル名展開はしません。

コマンド例と実行結果

 

 

 

標準出力と標準エラー出力のリダイレクト

標準出力と標準エラー出力の両方を同じファイルにリダイレクトする方法はいくつかあります。例えば、

>word 2>&1

があります。しかし、もっと短い形式として、

&>word
>&word

があります。この場合、'&>word'の方が好まれます。

同様にファイルに追記する場合でも

>>word 2>&1

の短い形式として、

&>>word

があります。

コマンド例と実行結果

 

 

 

参考

GNU Bash manual