
質問
パイプが実際に存在するときにパイプにリダイレクトするためにシェルが、およびのよう<<<
な< <(command)
代替を実装するのはなぜですか?< /dev/fd/*
stdin
はい
方式|
(クラシックパイプライン)
echo 'text' | sed 's/x/y/'
# or
cat - | sed 's/x/y/' # type text afterwards
<<<
道路
sed 's/x/y/' <<< 'text'
< <(command)
道路
sed 's/x/y/' < <(echo 'text')
# while <(command) becomes a file descriptor like
sed 's/x/y/' < /dev/fd/42
みんな戻ってきてくださいteyt
。
答え1
ソトは主に審美的な理由に興味を持っていましたが、技術的な理由もありました。たとえば、パイプラインは右側に子プロセスを作成することがよくあります。つまり、後で使用したい状態や変数を設定できないという意味です。比較する:
$ echo foo > file
$ line=bar; cat file | read -r line; echo "$line"
bar
$ line=bar; read -r line < file; echo "$line"
foo
答え2
パイプはプロセスから供給されるべきです。リダイレクトには<
プロセスは必要なく、ファイルとして提供できます。リダイレクト<
もずっと前に作成され、タスクが<<<
発明されました。<( ...)
>
出力方向の再指定に対する補完(対応)でもあります。お互いを補完する基本機能を持つことは良いことです。
答え3
ファイルから入力をリダイレクトする場合は、効率(Sotto Voceが指摘したprogram <file
ようにcat file | program
)に加えて、プログラムがファイルに直接アクセスできるため、ファイルを最初から最後まで読み取ること以外の操作を実行できます。 。いくつかの例:
ファイルから誤った順序で読み取ることがあります。を使用すると、
cat hugefile | tail
プログラムtail
は最後まで到達するためにファイル全体を読み取る必要がありますtail <hugefile
。lseek()
問題を起こすことなくファイルの一部のみを読み取ることができます。を使用すると、
head <hugefile
必要なhead
内容を読み、終了します(ファイルは閉じます)。ただし、使用すると、パイプを終了して閉じたcat hugefile | head
ときにまだ宛先がないパイプにデータをプッシュしようとします。この問題を解決するために、システムはに信号を送信します。多くのプログラムは、インポート時にエラーメッセージを表示します。私がテストしたバージョンではこれを行いませんでしたが、エラー状態で終了しました。これが設定スクリプトとモードスクリプトにある場合(例:head
cat
SIGPIPE
cat
SIGPIPE
cat
-e
pipefail
「非公式バッシュ厳格モード」)、bashはそれを致命的なエラーとして扱い、スクリプトを終了します。 (この種はお勧めできませんset -e
。)ファイルのプロパティにアクセスできます。を使用している場合
pv <hugefile | slowprocessor
(pv
「パイプラインビューア」ユーティリティ)は、ファイルサイズを確認し、これまでに転送されたファイルの割合と予想完了時間を示す進行状況バーを提供します。しかし、もしcat hugefile | pv | slowprocessor
あなたがpv
使用している場合(注:実際にファイルのサイズを明示的に知らせるオプションがpv
あります。)-s
したがって、全体的に入力ファイルへの直接アクセスは、プログラムがファイルを使用する方法においてより柔軟性を提供します。
また、多くのプログラム(ここで例として使用するすべてのプログラムを含む)を使用すると、入力ファイルをコマンド引数として直接指定できます(たとえば、tail hugefile
代わりに)。これはプログラムを可能にします。tail <hugefile
cat hugefile | tail
でも情報を提供し、ファイルにアクセスする方法を制御します。また、(この機能をサポートするコマンドの場合でも)複数の入力ファイルを許可しますcat |
。したがって、通常、これをサポートするコマンドのパイプまたは入力リダイレクトよりも優先されます。