web-dev-qa-db-ja.com

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

シェルスクリプトでファイル記述子を使用する方法を理解するのに非常に苦労しています。

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

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でこれを使用するとはるかに速くなると主張していますが、理解できません。まともなチュートリアルへのリンクをいただければ幸いです。私はグーグルパワーが私を失敗させているようです。

33
Ricko M

まず、閉じるための構文は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タグを参照することによるリダイレクトの例 があります。

開いている各ファイルにはファイル記述子が割り当てられ、stdinのファイル記述子は0ですstdoutは1です
stderr is 2追加のファイルを開くために、記述子3〜9が残ります。

例をとる

exec 3>&1 4>&2
exec 1>  /proc/1/fd/1 2>&1

3>&1は、新しいファイル記述子を作成し、STDOUTである1にリダイレクトします4>&2新しいファイル記述子も追加し、STDERRである2にリダイレクトします。

1> /proc/1/fd/1はソケットファイル記述子を使用します2>&1はまた、このファイル記述子からSTDOUTである1にすべてをリダイレクトします。

私も最近これをかなり学んだので、何かが足りない場合は遠慮なく指摘してください

Execの使用とファイルの説明を使用したリダイレクトのリファレンス https://www.linuxtopia.org/online_books/advanced_bash_scripting_guide/x13082.html

0
Altanai Bisht