web-dev-qa-db-ja.com

リダイレクトするためだけに猫にパイプするのはなぜですか?

私は時々次のようなものを見ます:

cat file | wc | cat > file2

なぜこれを行うのですか?

結果(またはパフォーマンス)が単純に(有利に)異なるのはいつですか。

cat file | wc > file2
29
OJFord
_cat file | wc | cat > file2
_

機能的には次のように機能するため、通常はcatの2つの役に立たない使用法になります。

_< file wc > file2
_

ただし、以下の場合があります。

_cat file | wc -c
_

以上

_< file wc -c
_

これは、多くのwc実装が通常のファイルに対して行う最適化を無効にすることです。

通常のファイルの場合、ファイルのコンテンツ全体を読み取らずに、ファイルのstat()システムコールを実行して、iノードに格納されているサイズを取得するだけで、ファイルのバイト数を取得できます。

たとえば、次の理由により、ファイルを読み取ることができます。

  • stat()情報は信頼できません(Linuxの_/proc_または_/sys_の一部のファイルなど):

    _$ < /sys/class/net/lo/mtu wc -c
    4096
    $ cat /sys/class/net/lo/mtu | wc -c
    6
    _
  • どれだけのデータを読み取ることができるかを確認したい(ハードドライブが故障した場合など)。
  • データの読み取り速度に関するベンチマークを取得したいだけです。
  • ファイルのコンテンツをメモリにキャッシュする必要があります。

もちろん、それらは例外です。一般的なケースでは、パフォーマンス上の理由から_< file wc -c_を使用します。


これで、使用したいシナリオをさらに遠くまで想像できます:_cat file | wc | cat > file2_:

  • 多分wcには、catが許可されている間は、ファイルへの読み取りまたは書き込みを禁止するapparmorプロファイルまたはその他のセキュリティメカニズムがあります(これは前代未聞でしょう)。
  • 多分catは(> 2のように)大きなものを扱うことができます32 バイト)ファイル。ただし、そのシステムではwcではありません(これまで、一部のシステムでは、一部のコマンドでこれが必要でした)。
  • _file2_を開いていない場合でも、wc(および最初のcat)を実行してファイル全体を読み取る(そして最後の最後で強制終了する)必要があるかもしれません。書き込み。
  • fileのコンテンツのオープンまたは読み取りの失敗(終了ステータス)を隠したい場合があります。 _wc < file > file2 || :_の方が理にかなっていますが。
  • lsofからWordカウントを取得している、または_file2_にWordカウントを保存しているという事実を(file(開いているファイルのリスト)の出力から)非表示にしたい場合があります。 。
32

これらの例は両方とも 猫の無駄な使用 です。どちらもwc < file1 > file2と同等です。この例でcatを使用する理由はありませんが、動的に出力を生成するものの一時的な代用としてcat fileを使用している場合を除きます。

37
larsks

私はそれが「猫の無用な使用」であると言うことについての議論に同意しませんが、canには理由があります:

多くの言語(英語を含む)では、単語と文は左から右に読み取られるため、同じ方法でデータの流れを示すと、読者にとってより自然に見えます。

2番目のcatの理由は、戻りコードをマスクするためである可能性があります。といった:

$ wc < /etc/passw
sh: /etc/passw: Cannot find or open the file.
$ echo $?
1

catの場合:

$ wc < /etc/passw | cat
sh: /etc/passw: Cannot find or open the file.
$ echo $?
0

シェルにset -e セットする。最初の例では、これはwcの後にシェルを中止しますが、後者の例では続行します。これに対処する方法は他にもあります。

また、2つのステートメント(つまり、猫の有無にかかわらず)のパフォーマンスの違いはごくわずかであり(特に、今日のマシンでは)、それが重要である場合、Shellは不適切な言語です。

17
DarkHeart

progが新しいサブプロセスをforkして終了し、新しいサブプロセスが標準出力に何かを書き込んでから終了するとします。

次に、コマンド

prog

サブプロセスが終了するのを待たず、シェルプロンプトが早く表示されます。しかし、コマンド

prog | cat

catの標準入力でEOFを待機します。これはサブプロセスが終了するのを効果的に待機します。したがって、これはcatの便利な使用法です。

9
pts