ファイル記述子とシェルスクリプト


32

シェルスクリプトでファイル記述子を使用する方法を理解するのは非常に困難です。

私は次のような基本を知っています

exec 5 > /tmp/foo

したがって、書き込み用にfd 5がfooに添付されます。

exec 6 < /tmp/bar

…読書のため。

exec 5>&-

…fdを閉じます。

今、これは何をしますか?

#!/bin/bash

exec 5 > /tmp/foo 
exec 6 < /tmp/bar 

cat <&6 | while read a
do
     echo $a >&5
done

私は理解して&5いるように、fdを閉じますので、各呼び出し後に出力がどのように正常にリダイレクトされていますか?

これはからのコピーパスタです:ここ

これをシンプルに使用echo $a > fileすると、はるかに速くなると主張していますが、理解できません。適切なチュートリアルへのリンクをいただければ幸いです。私はグーグルパワーが私に失敗しているようだ。

回答:


44

最初に、ファイル記述子が書き込み用に読み取られているか読み取り用に読み取られているかに応じて、閉じるための構文が5>&-またはであることに注意してください6<&-。そのブログ投稿にはタイプミスやフォーマットの不具合があるようです。

これがコメント付きスクリプトです。

exec 5>/tmp/foo       # open /tmp/foo for writing, on fd 5
exec 6</tmp/bar       # open /tmp/bar for reading, on fd 6
cat <&6 |             # call cat, with its standard input connected to
                      # what is currently fd 6, i.e., /tmp/bar
while read a; do      # 
  echo $a >&5         # write to fd 5, i.e., /tmp/foo
done                  # 

ここで終わりはありません。この単純な例では、すべての入力と出力が同じ場所に送られるため、追加のファイル記述子を使用する必要はありません。あなたは書くことができます

cat </tmp/bar |
while read a; do
  echo $a
done >/tmp/foo

明示的なファイル記述子の使用は、複数のファイルに順番に書き込む場合に役立ちます。たとえば、データをデータ出力ファイルに出力し、データをログファイルに記録し、場合によってはエラーメッセージも記録するスクリプトを考えます。つまり、データ用、ログ用、エラー用の3つの出力チャネルを意味します。出力用の標準記述子は2つしかないため、3つ目の記述子が必要です。exec出力ファイルを開くために呼び出すことができます:

exec >data-file
exec 3>log-file
echo "first line of data"
echo "this is a log line" >&3

if something_bad_happens; then echo error message >&2; fi
exec >&-  # close the data output file
echo "output file closed" >&3

次のように、ループ内にリダイレクトがある場合、効率についての説明が出ます(最初はファイルが空であると仮定します)。

while …; do echo $a >>/tmp/bar; done

各反復で、プログラム/tmp/barはファイルを開き、ファイルの最後までシークし、データを追加してファイルを閉じます。ファイルを一度だけ開く方が効率的です:

while …; do echo $a; done >/tmp/bar

異なる時間に複数のリダイレクトが発生する場合exec、リダイレクトでブロックをラップするのではなく、リダイレクトを実行するための呼び出しが役立ちます。

exec >/tmp/bar
while …; do echo $a; done

このサイトのタグを参照すると、リダイレクトのio-redirection他の例がいくつか見つかります。


1
ファイル記述子を閉じるためのどちらの構文も、実際には同じことを行います。
user1338062
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.