「猫の無駄な使用」に関する一般的なコンセンサスは何ですか?


39

grep、sed、trなどの複数のUNIXコマンドをパイプ処理するとき、catを使用して処理されている入力ファイルを指定する傾向があります。のようなものcat file | grep ... | awk ... | sed ...

しかし最近、これが猫の無用な使用であることを示す私のコメントにいくつかのコメントを残した後、私はここで質問するだろうと思いました。

私はこの問題を調べて、ウィキペディアのUUOC猫の役に立たない使用に関する記事に出会いました。

私がここで出会った最も近い質問はこれでした:猫を呼ぶのはもったいないですか?–しかし、それは私が求めているものとはまったく異なります。

UUOCキャンプではcmd1 args < file | cmd2 args | cmd3 ..、コマンドを使用すること、またはコマンドにファイルから読み取るオプションがあり、ファイルを引数として渡すことを提案していると思います。

しかし、私にcat file | cmd1 ... | cmd2は読みやすく理解しやすいようです。入力ファイルをさまざまなコマンドに送信するさまざまな方法を覚える必要はなく、プロセスは論理的に左から右に流れます。最初の入力、次に最初のプロセス...など。

猫の無用な使用についてどのような議論がなされているのか理解できていませんか?2秒ごとに多くの処理を実行するcronジョブを実行している場合、catは無駄になる可能性があることを理解しています。しかし、そうでなければ猫の使用に関する一般的なコンセンサスは何ですか?


14
ここで、catへの呼び出しは非効率的かもしれませんが、コマンドを理解して後で編集するのがはるかに簡単になり、(重要なことに、IMO)それぞれのコマンドを1つのジョブだけに分けて、全体をはるかに扱いやすくしますと。
-Phoshi

3
一般的なコンセンサスは、コンセンサスがないということです。
jwg

2
これは、stackoverflow.com / questions / 11710552 / useless-use-of-catの大部分を複製します(以前のものですが)。
トリプリー

1
< file cmd1 args | cmd2 args ...これも機能することを忘れないでください。そのため、「左から右」の引数は無効です。私はしばしば明確にするためにそれを使用します-私が示した順序は人々を一時停止させる可能性があり、これは良くありません。より多くのスレッド数が標準になっているため、これはIMOの問題になりつつあります...
Attie

回答:


21

そのように使用しても、他のことは何も達成されず、おそらくより効率的なオプションでは達成できないという意味で役に立たない(つまり、適切な結果を生成する)。

しかしcat、単なるよりもはるかに強力ですcat somefileこの答えで私が書いたものを調べるman catか読んでください。ただし、単一のファイルのコンテンツのみが絶対に必要な場合は、ファイルのコンテンツを取得するために使用しないことでパフォーマンス上の利点が得られる場合があります。cat

読みやすさに関しては、これはあなたの個人的な好みに依存します。cat特にパフォーマンスの側面が無視できる場合は、同じ理由でファイルを他のコマンドに取り込むのが好きです。

また、スクリプトの内容にも依存します。それがあなたのデスクトップマシンのためのあなた自身のシェルと便利な方法であるならば、あなた以外の誰も気にしません。チェーン内の次のツールがシークできる方が良いケースに出くわし、これを頻繁に使用されるソフトウェアとして、パフォーマンスの低いルーターまたは同様のデバイス上の最小限のLinuxシステムで配布する場合処理能力、それは違います。常にコンテキストに依存します。


1
パフォーマンスコストは無視できますか?多くの場合、それらは:oletange.blogspot.dk/2013/10/useless-use-of-cat.html
Ole

15

毎日のコマンドライン使用では、それほど大きな違いはありません。を使用しないことでCPUの時間が回避されるため、特に速度の違いに気付かないでしょうcat。CPUはアイドル状態になります。非常に負荷の高いシステム(負荷平均/ N CPU> 1)でない限り、数百または数千(または数十万)のアイテムをすべての実用性でループしていても、大きな違いはありません。

ゴムが道路と出会う場所は、良い習慣を形成し、悪い習慣を阻止することです。かびの生えた決まり文句を引き出すために、悪魔は細部に宿っています。そして、平凡なものと偉大なものを分けるのは、このような詳細です。

車を運転しているときのように、なぜ3つの権利を得ることができるのに、なぜ左折するのですか?もちろんできますし、完璧に機能します。しかし、左折の力を理解すると、3つの権利はばかげているように見えます。

1つのファイルハンドル、17kのRAM、0.004秒のCPU時間を保存することではありません。UNIXを使用するという哲学全体です。私のイラストの「左折の力」は、単に入力をリダイレクトするだけではなく、UNIXの哲学です。これを完全に理解することで、あなたはあなたの周りの人々よりもはるかに優れたものになり、あなたは理解している人々から尊敬を集めるでしょう。


信号機のない6車線の混雑した高速道路で左折することを考えている場合は、右折するか、別のルートを取ることを検討する必要があります。* nixでは、いくつかのルートを選択できます。個人の好みと読みやすさの問題です。「cat file | cmd1 | cat | cmd2 | more」にしたい場合は、先に進みます。(cmd1がページングする場合に役立つことがあります-catはそれを削除します。)$ CPU時間<< $ Brain時間。
MikeP

1
@MikeP catはページネーションを削除しませんが、何かにパイプする一部のアプリケーションによるページングが削除される場合があります。
トリプリー

12

cat file | myprogram例でよく使用します。時々私は猫の無用な使用で告発されていますhttp://www.iki.fi/era/unix/award.html)。次の理由で同意しません。

  • 何が起こっているかを理解するのは簡単です。

    UNIXコマンドを読み取る場合、コマンドの後に引数が続き、その後にリダイレクトが必要です。リダイレクションをどこにでも配置すること可能ですが、めったに見られません。そのため、例を読むのが難しくなります。私は信じている

    cat foo | program1 -o option -b option | program2
    

    より読みやすい

    program1 -o option -b option < foo | program2
    

    リダイレクトを最初に移動すると、この構文に慣れていない人を混乱させることになります。

    < foo program1 -o option -b option | program2
    

    そして例は理解しやすいものでなければなりません。

  • 変更は簡単です。

    プログラムがcatから読み取ることができることがわかっている場合、通常、STDOUTに出力するプログラムから出力を読み取ることができると想定できるため、独自のニーズに合わせて予測可能な結果を​​得ることができます。

  • STDINがファイルでない場合、プログラムが失敗しないことを強調します。

    program1 < foo動作する場合は動作することを想定することは安全ではありませんcat foo | program1。しかし、ある反対のことを想定して、実際に安全。STDINがファイルの場合、このプログラムは機能しますが、入力がパイプの場合、seekを使用するため失敗します。

    # works
    < foo perl -e 'seek(STDIN,1,1) || die;print <STDIN>'
    
    # fails
    cat foo | perl -e 'seek(STDIN,1,1) || die;print <STDIN>'
    

私は上のパフォーマンスの低下を見てきましたhttp://oletange.blogspot.dk/2013/10/useless-use-of-cat.html結論は使用しないされcat file |、処理の複雑さは、単純なgrepのと似ている場合パフォーマンスは読みやすさよりも重要です。他の状況でcat file |は大丈夫です。


11

UUOCであるとコメントしている人たちが取っている立場は、Unixとシェルの構文を本当に理解していれば、そのコンテキストでcatを使用しないということです。貧弱な文法を使用しているように見えます:貧弱な文法を使用して文章を書くことができますが、それでもポイントを得ることができますが、言語に対する理解が不十分であり、ひいては教育が不十分です。だから何かがUUOCであると言うことは、誰かが彼らが何をしているのか理解していないと言う別の方法です。

効率性に関しては、コマンドラインからパイプラインを実行cat somefile |している場合、を使用する方が効率的かどうかを考えるよりもマシンの実行時間が短くなります< somefile。どうでもいい。


6
かなり長い間、cat somefile | prog猫なしでシェルで表現する他の方法があることを知っていましたがprog < somefile、それらは常に間違った順序になっているようでした、特にコマンドのチェーンが一緒にパイプされています。今、私< somefile progはトリックと同じくらいエレガントな何かを見る、ありがとう。私は猫を使うために残した言い訳を使い果たしました。
アレックス14年

4

受賞者の一人が私の答えの1つとしてUUOCをピン留めしようとする今日まで、この賞を知っていませんでした。でしたcat file.txt | grep foo | cut ... | cut ...。私は彼に私の心の一部を与えました、そして、そうすることをした後にだけ、彼は賞の起源とそうする習慣について言及してくれました。さらに検索すると、この質問につながりました。意識的な検討にもかかわらず、やや残念ながら、答えのどれにも私の理論的根拠は含まれていませんでした。

私は彼を教育するときに守備するつもりはありませんでした。結局のところ、私の若い年にはgrep foo file.txt | cut ... | cut ...、頻繁にシングルを実行するたびにgrepファイル引数の配置を学び、最初のものがパターンであり、後のものがファイル名であることを知っているので、コマンドを書いたでしょう。

私はcat接頭辞で質問に答えたとき、意識的に選択しました。「Linus Torvaldsの言葉で」「良い味」の理由のために部分的に、しかし主に機能の説得力のある理由のため。

後者の理由はより重要なので、最初に説明します。ソリューションとしてパイプラインを提供するとき、再利用できると期待しています。パイプラインは、最後に追加されるか、別のパイプラインにスプライスされる可能性が非常に高いです。その場合、grepへのファイル引数があると再利用性が損なわれ、ファイル引数が存在する場合はエラーメッセージなしで静かに実行される可能性が非常に高くなります。I. e。grep foo xyz | grep bar xyz | wcどのように多くの行であなたを与えるxyz含まれていbarますが、両方を含む行の数を期待されている間fooとをbar。使用する前にパイプラインのコマンドの引数を変更する必要があると、エラーが発生しやすくなります。それに静かな失敗の可能性を加えてください、そして、それは特に陰湿な習慣になります。

前者の理由も重要ではありません。なぜなら、多くの「良い味」は、教育を必要としている人が「ではなくその猫は役に立たない」。

しかし、私が言及した前の「良い味」の理由を意識することも試みます。その理由は、Unixの直交設計の精神に関係しています。grepしませんしcutlsしませんgrep。したがって、少なくともgrep foo file1 file2 file3デザインの精神に反します。直交する方法はcat file1 file2 file3 | grep fooです。さて、これgrep foo file1は単にの特殊なケースでありgrep foo file1 file2 file3、同じように扱わなければ、少なくとも無駄な猫賞を避けようとする脳時計サイクルを使い果たしていることになります。

それは私たちをgrep foo file1 file2 file3連結している議論に導き、cat連結しているので適切cat file1 file2 file3ですcatが、連結していないcat file1 | grep fooので、私たちはcat全能のUnixの精神に違反しています。そうだとすれば、Unixは1つのファイルの出力を読み取り、それを標準出力に吐き出すために別のコマンドを必要とします(ページネーションや、純粋な標準出力への吐き出しではありません)。だから、あなたが言うような状況を持っているだろうcat file1 file2か、と言うdog file1と誠実避けるために覚えてcat file1も回避しながら、賞を避けるためにdog file1 file2のうまくいけば設計するのでdog、複数のファイルが指定されている場合、エラーをスローしていました。

この時点で、ファイルをstdoutに吐き出すための別のコマンドを含めず、cat他の名前を付けるのではなく連結するために命名することについて、Unixデザイナーに同情することを願っています。<edit>そのような犬、不幸な<オペレーターがいます。残念ながら、パイプラインの最後に配置すると、構成が容易になりません。最初に配置する構文的または審美的にきれいな方法はありません。また、一般的ではないため、犬から始めて、前のファイルの後に処理したい場合は別のファイル名を追加するだけでも残念です。(>一方、半分ほど悪くはありません。最後にほぼ完璧な配置があります。通常、パイプラインの再利用可能な部分ではないため、象徴的に区別されます。)</edit>

次の質問は、それ以上の処理をせずに、単にファイルを吐くコマンド、または複数のファイルを標準出力に連結するコマンドを持つことが重要なのはなぜですか?1つの理由は、標準入力で動作するすべてのUnixコマンドが少なくとも1つのコマンドラインファイル引数を解析し、存在する場合は入力として使用する方法を知ることを避けるためです。2番目の理由は、ユーザーが覚えておく必要がないようにするためです。(b)上記のサイレントパイプラインバグを回避します。

これが、なぜgrep追加のロジックがあるのかを示しています。その理由は、頻繁に使用されるコマンド(パイプラインとしてではなく)をスタンドアロンで使用できるようにすることです。これは、使いやすさを大幅に向上させるための直交性のわずかな妥協です。すべてのコマンドをこのように設計する必要はありません。頻繁に使用しないコマンドは、ファイル引数の余分なロジックを完全に回避する必要があります(余分なロジックは不必要な脆弱性(バグの可能性)につながります)。例外は、の場合のようにファイル引数を許可することですgrep。(ところでls、ファイル引数を受け入れるだけでなく、ほとんど必要とするまったく異なる理由があることに注意してください)

最後に、標準入力が利用可能な場合にgrep(必ずしもではありませんls)などの例外的なコマンドがエラーを生成する場合は、より良い方法があります。コマンドには、ユーザーの利便性のために万能のUnixの直交精神に違反するロジックが含まれているため、これは合理的です。ユーザーの利便性を高めるため、つまり無音障害による苦痛を防ぐために、このようなコマンドは無音障害の可能性がある場合にユーザーに警告することにより、自分の違反に違反することをためらわないでください。


1
この回答と質問のクロスサイト複製で説明したように、grep pattern f1 f2 f3単純な連結はありませんgrepファイルを認識し、ファイル名(およびオプションで行番号など)を出力します。 grep . /sys/kernel/mm/transparent_hugepage/*ファイル名を印刷するための素晴らしいハックです:単一行のファイルがたくさんあるファイルコンテンツ。Unixの古典的な設計では、ほとんどのユーティリティは*.txt必要なく動作しますcatcat複数のファイルを1つのストリームに統合するためのものです。
ピーター

@PeterCordes grepについてはあまり書きませんでした。エラー/コピー&ペーストに対する堅牢性に関して、私が観察した実質的な問題があります。正確さ対パフォーマンス、あなたは都合の良いことに無視することを選択しました。
randomstring

特に、パイプラインのコピー/貼り付け時に発生する可能性のあるエラーについて、いくつかの興味深い有効なポイントを作成します。あなたのgrep例を、cut複数のファイルを気にする理由がなく、常に標準入力から供給されるようなプログラムに置き換えることをお勧めします。一部のユーティリティは、のようにtr、すべてのファイルの引数を受け入れ、フィルタとしてのみ機能するので、選択が間にありませんcat<
ピーター

1
投稿に関する私の最大の問題は、入力リダイレクトを割引することです。 <file cmd1 | cmd2 >out素晴らしくありませんが、私は認めますが、それに慣れることは完全に可能です。あなたは「万能Unixの精神」についてあざける方法で続けていますが、Unixのデザイナーが本当に考えていた方法を理解していない、または取得したくないように聞こえるので、私にとっては完全にフラットになります。Unixの設計が気に入らなくても大丈夫ですが、本質的に愚かではありません。OSの設計がシェル構文よりも前であるかどうか、そしてそれがどのように進化したかはわかりませんが、cat1970年に余分なものを避ける価値がありました!
ピーター

1
@PeterCordes後知恵では、私は答えにかなり時間を費やしていました。これは最も重要な点-最初に正確さ、2番目に最適化-を損ないます。余分なものcatはパイプラインの再利用とスプライスに役立ちますが、それなしではサイレントエラーが発生する可能性があります(私の答えで「黙って」検索してください)。
ランダムストリング

2

猫の無用な使用を守るために

(しつこいコメントの津波とこの慣行とのバランスをとるためのいくつかの段落)

私は、bashをシェルとして、また小さなスクリプトのスクリプト言語として(そして、それほど小さくないスクリプトに対しては残念なことに)長年にわたってbashを使用しています。ずっと前に、私は「猫の役に立たない使用」(UUoC)について学びました。私は少なくとも毎週それについてまだ罪を犯していますが、率直に言って、それを避けるために少しでも強いられることはほとんどありません。catvs を使用する< fileことは技術的な違いよりも味に関することであると信じており、私の好みを共有するLinuxを初めて使用する人々を保護するためにこの回答を書きました。cat彼らのやり方に重大な問題があると考えることから(そして、いくつかの機会があることに注意してください)。Linus Torvaldsのように、私はしばしば味よりもスキルよりも重要だと考えています。それは私の味があなたよりも良いという意味ではありませんが、何か悪い味があれば、価値のあるものを得ることなくそれをしないということです。

それは質問の作者のようなことをすでに明らかだ私は感じて、私はインクリメンタルに複雑なコマンドを構築することにより、問題を探求していますbashのようなREPL上で作業するときに猫を使用することは非常に自然であること。非常に典型的な例を次に示します。テキストファイルがあり、それについてあまり知りません。cat file内容の味を取得するために入力します。場合は、出力が多すぎると、私は私の最大の矢印を押すと、状況に応じてよ、私は追加します| head| grep fooまたは| what_ever処理ステップを追加することによって、私の前のコマンドを拡張します。このように、1つの処理ステップを追加することで、単純なコマンドからより複雑なコマンドに段階的に進むこの方法は非常に自然に感じます(私はipythonでも同じことをやっていて、この方法が大好きですpyfunctional同様のプログラミングツールがこのスタイルを網羅しています)。bashシェルで作業するときだから、私は「削除するには、私の流れを中断することを確信メートルcat、より役に立たない、それは例99.9%で、全く...よく何の結果でないと苦しむせてより。

もちろん、スクリプトを書くとき、物事変わるかもしれません。しかし、スクリプトを作成するときでさえ、UUoCをock笑する人はこの重要な教訓を「早すぎる最適化はすべての悪の根源」という偉大な心で無視しているというのが私の意見です。また、非定型的なことをしていない場合、最適化が必要な場所にUUoCを配置するのは非常に困難です。もちろん、あなたはそれについて何が非効率であるかを確実に知る必要があります(それが言及しているように思われないので、それは余分なプロセス呼び出しBTWです)。プロセスの呼び出しに費用がかかるようなまれなシステム(たとえば、一部の組み込みシステムやCygWinの程度は低い)で作業する場合、その知識があれば、特別な状況で必要な場合の対処方法を知ることができます。たとえば、自分が電話していることに気付いた場合catループで1秒間に何度も(その位置にいる場合は、bashが仕事に適したツールかどうかを自問してください)。繰り返しますが、「最初に正しく動作させ、必要に応じて最適化します」

そして、UUoCニックに関する苦情の津波をどのように説明しますか?

ほとんどのUnix-新参者は知らないだろう。誰もが私の好みを持っていないだけでなく、私は非常に多くの人々がUUoC文句を言う理由の大部分は、技術的な人間ではないことを信じて< file command、それがプレーするより経験豊富な人には魅力的ですので、イディオム「オールド・達人を「彼らに。また、彼は派手な言葉(「プロセス呼び出し」)を使用し、「最適化」という親愛なる主題に触れる機会を得ます。良い印象が保証されるので、抵抗するのは非常に難しいです。その後、新参者は額面通りに達人のアドバイスを受け取り、長い間それを「唯一の真実」として他の人にリプレイします(そしてこの答えに反対票を投じます:-)。おもしろい注意:UUoCの非効率性を避けるためにbashを修正するのはおそらく非常に簡単なので、なぜこの機能を追加したり、< filename長い年月を経てファイルを猫。暗い魂は、一部の灰色ひげのバッシュハッカーが私たちをm笑する機会を残したいことを示唆するでしょう;-)


+1この実践を広める人類学的要因がなぜあるのかについての最後の段落を愛してください:-)
randomstring

1

本当に素晴らしいのは、次のような構文をサポートするシェルです。

< filename cmd | cmd2 cmd2arg1... | cmd3

それまではcat filename | realcmd1...、引数としてファイル名を必要とする初期コマンドで標準化された構文を保持しているため、受け入れられると思います。


17
Bashおよび同様のシェルがサポートし< filename cmd | cmd2 ...ます。それで十分ですか?
ゲイリージョン

@garyjohn:それを答えとして投稿すべきだと思う。
ケビンリード

14
義務的な古いシェルハッカーのコメント:Bourneスタイルのシェルは< file command ...、少なくとも80年代半ば以降、おそらくオリジナルshが書かれた70年代まで遡ります。より一般的には、I / Oリダイレクトは左から右に解析され、コマンドライン内で任意の順序で散在させることができます。だから、cmd <file arg arg...また有効だろう。
デールハグルンド

3
ええ、それは私がUUOCを発明したのは、タイプするのがどれほど簡単かということもあります。
ランダルシュワルツ

2
シフトされた1つのキャラクターとシフトされていない4つのキャラクターはそれほど大きな違いではなく、ファイルをプロンプトにパイプで送るたびに頭痛がするのではなく、電話でもほとんど気付かない余分なプロセスを生成したい。
アーロンミラー

0

猫は「匂いが良い」または「読みやすい」ので、猫の使用は受け入れられると言っている人なら誰でも、これを言うだけです:

多分あなたに...しかし、あなたのコードを読んだり、理解しようとする他の人には。あなたがあなたの例で他の人に指示したりコードを共有したりすることを決して試みないなら、ぜひあなた自身の暇なときにそれを使ってください。

また、このコメントを追加します。長い間Linuxユーザーであり、Admin / Engineer ...(そして私たちの多くがいます)、私たちの目を出血させます。どうして?リソースを厳しく管理しているシステム上のリソースを使用するためです。catコマンドとパイプ自体は、完全に役に立たない余分なメモリとファイルハンドルを使用します。あなたは私のシステムが無料で必要とするリソースを縛り、あなたはこれらのリソースの使用法を説明できる何も得ていない。これは巨大です。

今、私はここに座って誰とでもコードの匂いや読みやすさのようなことを一日中議論することができますが、一日の終わりには書き込みや間違った問題であり、システム上のリソースを使用しても何も得られません...間違っています。

ホームユーザーとして、あなたは私のアドバイスから学び、物事を行うためのより良い方法を学ぶことができます。また、猫の「匂い」に目がくらむことを選択することもできます。常にこの練習をしているので、あなたは彼らが正しいことを黙って認めなければならず、あなたはそれが真実だから頑固です。:-)


私はまた、長年のLinux(および以前の* nix)ユーザーおよびソフトウェア開発者でもあります。見るために「それは私達の目を出血させる」と言うときあなたは私のために話さないcat foo.txt | ...。もう1つの答えは、なぜそれが適切な使用法になるのかをよく説明しています。好意的なケースの簡単な要約は、「$ CPU時間<< $ Brain時間」(@MikePが上記でコメントしたように)です。
ジムデラハント

最初に、それは2017年からの答えでした(死んだLOLを復活させる方法)。第二に、管理者または開発者として、可能な限りリソースの使用を最小限に抑えるよう常に努力する必要があることに注意してください。アプリやサービスを作成するとき、正しいアプリ/サービスにほとんどまたはまったく利益をもたらさないメモリまたはCPUドレインを監視しようとしますか?まあUUOCはまさにそれです。今、猫の完全に有効な用途があります。私はコマンドへのパイピングを含むことを確信しています...ただ頻繁ではありません。あなたが言うように、私はあなたのために話さないかもしれません...しかし、あなたが専門家であるなら、なぜあなたはより容易に同意しないのだろうと思います(本当のUUOCシナリオを与えられた)。
デビッド・ドレッグス

問題は、開発者が最適化するためのコストはメモリまたはCPUのドレインだけではないことです。問題を理解し、実装を記述およびデバッグするための人的時間のコストもトレードオフの一部です。ここでの答えのいくつかは、人間の時間はメモリやCPUよりもはるかに少なく、高価であるという判断に基づいています。。…しかし、これは議論になりつつあり、ルールに反しています。回答に対する投票で、スーパーユーザーがどの視点を支持しているかについて話します。
ジムデラハント
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.