Was ist der allgemeine Konsens über den „nutzlosen Einsatz von Katzen“?


41

Wenn ich mehrere Unix-Befehle wie grep, sed, tr usw. übergebe, neige ich dazu, die Eingabedatei anzugeben, die mit cat verarbeitet wird. Also sowas wie cat file | grep ... | awk ... | sed ....

Aber kürzlich, nachdem ein paar Kommentare zu meinen Antworten hinterlassen wurden, die darauf hindeuten, dass dies eine nutzlose Verwendung von Katze ist, dachte ich, ich würde die Frage hier stellen.

Ich habe nachgeschlagen und bin auf den Artikel von Wikipedia zu UUOC und The Useless Use of Cat Award gestoßen, und es scheint mir, dass die vorgebrachten Argumente aus der Perspektive der Effizienz stammen.

Die naheliegendste Frage, der ich hier begegnet bin, war folgende: Ist es verschwenderisch, Katze zu nennen? - aber es ist nicht ganz das, wonach ich frage.

Ich vermute, was das UUOC-Lager vorschlägt, ist zu verwenden, cmd1 args < file | cmd2 args | cmd3 ..oder wenn der Befehl eine Option zum Lesen aus der Datei hat, dann die Datei als Argument weiterzugeben.

Aber für mich cat file | cmd1 ... | cmd2scheint es viel einfacher zu lesen und zu verstehen. Ich muss mich nicht an verschiedene Methoden zum Senden von Eingabedateien an verschiedene Befehle erinnern, und der Prozess verläuft logisch von links nach rechts. Erste Eingabe, dann der erste Vorgang ... und so weiter.

Verstehe ich nicht, welche Argumente über den nutzlosen Einsatz von Katze vorgebracht werden? Ich verstehe, dass, wenn ich einen Cron-Job ausführe, der alle 2 Sekunden ausgeführt wird und viel Verarbeitung ausführt, in diesem Fall Katze möglicherweise verschwenderisch ist. Aber was ist sonst der allgemeine Konsens über die Verwendung von Katze?


16
Ich bin damit einverstanden, dass der Aufruf an cat zwar ineffizient ist, aber das Verständnis und die spätere Bearbeitung des Befehls dadurch erheblich erleichtert wird. Außerdem wird (was wichtig ist, IMO) jeder Befehl in nur einen Job unterteilt, wodurch die Abwicklung des gesamten Vorgangs erheblich vereinfacht wird mit.
Phoshi

4
Der allgemeine Konsens ist, dass es keinen Konsens gibt.
Jwg

2
Dies dupliziert weitgehend stackoverflow.com/questions/11710552/useless-use-of-cat (obwohl es älter ist als es).
Tripleee

1
Vergiss nicht, dass das auch < file cmd1 args | cmd2 args ...funktioniert. Dein Argument von "von links nach rechts " ist ungültig. Ich benutze es oft, um Klarheit zu schaffen - die Reihenfolge, die ich gezeigt habe, kann dazu führen, dass Leute innehalten, was nicht gut ist. Je höher die Anzahl der Threads, desto weniger wird dies ein Problem, IMO ...
Attie

Antworten:


21

Es ist in dem Sinne nutzlos, dass eine solche Verwendung nichts bewirkt, was die anderen, möglicherweise effizienteren Optionen nicht können (dh angemessene Ergebnisse erzielen).

Aber catist viel mächtiger als nur cat somefile. Konsultieren man catoder lesen , was ich in dieser Antwort schrieb . Wenn Sie jedoch absolut nur den Inhalt einer einzelnen Datei benötigen, erhalten Sie möglicherweise einen Leistungsvorteil, wenn Sie catdie Dateiinhalte nicht abrufen.

Die Lesbarkeit hängt von Ihrem persönlichen Geschmack ab. Ich mag es cataus dem gleichen Grund, Dateien in andere Befehle zu schreiben, besonders wenn die Leistungsaspekte vernachlässigbar sind.

Es hängt auch davon ab, was Sie schreiben. Wenn es Ihre eigenen Shell- und Convenience-Methoden für Ihren Desktop-Computer sind, kümmert es niemanden außer Ihnen. Wenn Sie auf einen Fall stoßen, in dem es besser ist, das nächste Tool in der Kette zu suchen und als häufig verwendete Software auf einem minimalen Linux-System auf einem Router mit geringer Leistung oder einem ähnlichen Gerät mit realen Einschränkungen zu verteilen Verarbeitungsfähigkeit, das ist anders. Es kommt immer auf den Kontext an.


3
Sind die Leistungskosten vernachlässigbar? In vielen Fällen sind dies: oletange.blogspot.dk/2013/10/useless-use-of-cat.html
Ole Tange

15

In der täglichen Verwendung von Kommandozeilen ist das nicht viel anders. Sie werden insbesondere keinen Geschwindigkeitsunterschied bemerken, da die Zeit, die durch catNichtbenutzung der CPU eingespart wird, nur im Leerlauf ist. Selbst wenn Sie Hunderte oder Tausende (oder sogar Hunderttausende) von Elementen praktisch durchlaufen, wird es keinen großen Unterschied machen, es sei denn, Sie befinden sich auf einem stark ausgelasteten System (Load Average / N CPU> 1).

Wenn der Gummi auf die Straße trifft, geht es darum, gute Gewohnheiten zu entwickeln und schlechte zu entmutigen. Um ein schimmeliges Klischee herauszuholen, steckt der Teufel im Detail. Und es sind solche Details, die das Mittelmäßige vom Großen trennen.

Es ist wie beim Autofahren, warum nach links abbiegen, wenn man stattdessen nur drei Rechte machen kann? Natürlich kannst du das und es funktioniert perfekt. Aber wenn Sie die Macht der Linkskurven verstanden haben, dann scheinen drei Rechte einfach albern.

Es geht nicht darum, ein Dateihandle, 17 KB RAM und 0,004 Sekunden CPU-Zeit zu sparen. Es geht um die gesamte Philosophie der Verwendung von UNIX. Die "Kraft der Linkskurven" in meiner Illustration leitet nicht nur Eingaben um, sondern ist die UNIX-Philosophie. Wenn Sie dies voll und ganz tun, werden Sie weitaus besser abschneiden als Ihre Mitmenschen, und Sie werden denjenigen Respekt zollen, die das verstehen.


2
Wenn Sie überlegen, ohne Ampel nach links auf eine sechsspurige, stark befahrene Autobahn abzubiegen, ist es möglicherweise angebracht, nach rechts abzubiegen oder eine andere Route einzuschlagen. Mit * nix haben Sie die Wahl zwischen mehreren Routen. Es ist eine Frage der persönlichen Präferenz und Lesbarkeit. Wenn Sie "Katzendatei | cmd1 | Katze | cmd2 | mehr" möchten, fahren Sie fort. (Manchmal ist das nützlich, wenn cmd1 paginiert - cat wird es beseitigen.) $ CPU time << $ Brain time.
MikeP

1
@MikeP Die Funktion catbeseitigt keine Paginierung. Bei einigen Anwendungen kann jedoch die Paging-Funktion durch das Weiterleiten an eine bestimmte Stelle beseitigt werden.
Tripleee

14

Ich benutze oft cat file | myprogramin Beispielen. Manchmal werde ich beschuldigt, keine Katze benutzt zu haben ( http://www.iki.fi/era/unix/award.html ). Ich bin aus folgenden Gründen nicht einverstanden:

Es ist leicht zu verstehen, was los ist.

Wenn Sie einen UNIX-Befehl lesen, erwarten Sie einen Befehl, gefolgt von Argumenten und einer Umleitung. Es ist möglich, die Umleitung an einer beliebigen Stelle zu platzieren, sie wird jedoch selten gesehen. Dadurch fällt es den Menschen schwerer, das Beispiel zu lesen. Ich glaube

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

ist leichter zu lesen als

    program1 -o option -b option < foo | program2

Wenn Sie die Umleitung an den Anfang verschieben, verwirren Sie Personen, die nicht an diese Syntax gewöhnt sind:

    < foo program1 -o option -b option | program2

und Beispiele sollten einfach zu verstehen sein.

Es ist leicht zu ändern.

Wenn Sie wissen, dass das Programm von cat lesen kann, können Sie normalerweise davon ausgehen, dass es die Ausgabe von jedem Programm lesen kann, das an STDOUT ausgegeben wird. Auf diese Weise können Sie es an Ihre eigenen Bedürfnisse anpassen und vorhersagbare Ergebnisse erzielen.

Es wird betont, dass das Programm nicht fehlschlägt, wenn STDIN keine reguläre Datei ist.

Es ist nicht sicher anzunehmen, dass wenn es program1 < foofunktioniert, cat foo | program1es auch funktioniert. Aber es ist in der Praxis sicher das Gegenteil annehmen. Dieses Programm funktioniert, wenn STDIN eine Datei ist, schlägt jedoch fehl, wenn die Eingabe eine Pipe ist, da es seek verwendet:

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

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

Ich habe mir den Performance-Nachteil auf http://oletange.blogspot.dk/2013/10/useless-use-of-cat.html angesehen. Die Schlussfolgerung lautet, dass keine Verwendung möglich ist, cat file |wenn die Komplexität der Verarbeitung einem einfachen grep ähnelt und Leistung ist wichtiger als Lesbarkeit. Für andere Situationen cat file |ist in Ordnung.


1
Endlich eine Antwort mit aktuellen Benchmarks. In meinem Kommentar stelle ich auch fest, dass "manchmal" Katzen schneller sein können. Das einzige Mal, dass ich mir vorstellen kann, dass "unnütze Verwendung von cat" ein wirklicher Nachteil ist, ist, wenn Sie eine einfache Verarbeitung für riesige Dateien durchführen (oder wenn der Prozess stdin wie den Befehl tail in besonderer Weise nutzen kann) ... unix.stackexchange. com / a / 225608/8337
Rogerdpack

12

Ich denke, dass einige derjenigen, die sich zu etwas äußern, das ein UUOC ist, der Meinung sind, dass man cat in diesem Kontext nicht verwenden würde, wenn man Unix und Shell-Syntax wirklich versteht. Es wird so gesehen, als würde man schlechte Grammatik verwenden: Ich kann einen Satz mit schlechter Grammatik schreiben und trotzdem meine Argumente vermitteln, aber ich zeige auch mein schlechtes Sprachverständnis und damit meine schlechte Ausbildung. Zu sagen, dass etwas ein UUOC ist, ist eine andere Art zu sagen, dass jemand nicht versteht, was er tut.

Wenn Sie eine Pipeline über die Befehlszeile ausführen, dauert die Ausführung des Computers weniger lange als die Prüfung, cat somefile |ob die Verwendung möglicherweise effizienter ist < somefile. Es ist einfach egal.


6
Eine ganze Weile wusste ich, dass es auch andere Möglichkeiten gab, sich cat somefile | progin einer Muschel ohne Katze auszudrücken , prog < somefileaber sie schienen mir immer in der falschen Reihenfolge zu sein, besonders mit einer Kette von Befehlen, die aneinandergereiht waren. Jetzt sehe ich etwas so Elegantes wie < somefile progden Trick, danke. Ich habe keine Ausreden mehr, um Katze zu benutzen.
Alex

4

Ich war mir der Auszeichnung bis heute nicht bewusst, als ein Anfänger versuchte, die UUOC für eine meiner Antworten an mich zu binden. Es war ein cat file.txt | grep foo | cut ... | cut .... Ich gab ihm einen Teil meiner Meinung und besuchte erst dann den Link, den er mir gab, um auf die Ursprünge der Auszeichnung und die Praxis hinzuweisen. Weitere Suche führte mich zu dieser Frage. Etwas unglücklicherweise enthielt trotz bewusster Überlegung keine der Antworten meine Begründung.

Ich wollte nicht defensiv sein, wenn ich ihn erziehe. Schließlich hätte ich in meinen jüngeren Jahren den Befehl so geschrieben, als grep foo file.txt | cut ... | cut ...ob Sie bei jeder häufigen Single grepdie Platzierung des Datei-Arguments lernen und wissen, dass das erste das Muster und das spätere die Dateinamen sind.

Es war eine bewusste Entscheidung, als ich die Frage mit dem catPräfix beantwortete, teilweise aus Gründen des "guten Geschmacks" (in den Worten von Linus Torvalds), hauptsächlich aber aus zwingenden Gründen der Funktion.

Der letztere Grund ist wichtiger, also werde ich ihn zuerst herausbringen. Wenn ich eine Pipeline als Lösung anbiete, erwarte ich, dass sie wiederverwendbar ist. Es ist sehr wahrscheinlich, dass eine Pipeline am Ende einer anderen Pipeline hinzugefügt oder in eine andere gespleißt wird. In diesem Fall eine Datei Argument grep vermasselt Wiederverwertbarkeit aufweisen und ganz tun vielleicht so leise , ohne eine Fehlermeldung , wenn das Dateiargument vorhanden ist . Ich e. grep foo xyz | grep bar xyz | wcgibt an, wie viele Zeilen xyzenthalten sind, barwährend Sie die Anzahl der Zeilen erwarten, die sowohl fooals auch enthalten bar. Das Ändern von Argumenten in einem Befehl in einer Pipeline vor dessen Verwendung ist fehleranfällig. Wenn Sie die Möglichkeit stiller Fehler hinzufügen, wird dies zu einer besonders heimtückischen Praxis.

Der erstere Grund ist auch nicht unwichtig, da viel "guter Geschmack" lediglich eine intuitive unbewusste Begründung für Dinge wie die oben genannten stillen Fehler ist, an die man im Moment, in dem jemand, der Bildung benötigt, sagt "aber nicht", nicht denken kann diese Katze nutzlos ".

Ich werde jedoch versuchen, auch den erwähnten früheren "guten Geschmack" bewusst zu machen. Dieser Grund hat mit dem orthogonalen Designgeist von Unix zu tun. greptut nicht cutund lstut nicht grep. Das widerspricht also zumindest grep foo file1 file2 file3dem Designgeist. Die orthogonale Vorgehensweise ist cat file1 file2 file3 | grep foo. Jetzt grep foo file1ist es nur ein Sonderfall von grep foo file1 file2 file3, und wenn Sie es nicht gleich behandeln, verbrauchen Sie zumindest die Gehirn-Taktzyklen, um den unnützen Katzenpreis zu vermeiden.

Das führt uns zu dem Argument, grep foo file1 file2 file3das verkettet und catverkettet, so dass es angemessen ist, cat file1 file2 file3aber weil cates nicht verkettet, cat file1 | grep fooverletzen wir den Geist von sowohl dem catals auch dem allmächtigen Unix. Nun, wenn das der Fall wäre, würde Unix einen anderen Befehl benötigen, um die Ausgabe einer Datei zu lesen und auf stdout zu spucken (nicht paginieren oder irgendetwas anderes, nur auf stdout spucken). Sie würden also die Situation haben, in der Sie sagen cat file1 file2oder Sie sagen dog file1und gewissenhaft daran denken, cat file1zu vermeiden, die Auszeichnung zu erhalten, und gleichzeitig zu vermeiden, dog file1 file2da das Design von hoffentlich dogeinen Fehler auslösen würde, wenn mehrere Dateien angegeben werden.

Hoffentlich sympathisieren Sie an dieser Stelle mit den Unix-Designern dafür, dass sie keinen separaten Befehl enthalten, um eine Datei in stdout zu spucken, und gleichzeitig catfür die Verkettung einen Namen vergeben, anstatt einen anderen Namen zu vergeben. <edit>da ist so ein hund, der unglückliche <betreiber. Es ist bedauerlich, dass es sich am Ende der Pipeline befindet und sich nicht leicht zusammensetzen lässt. Es gibt keine syntaktisch oder ästhetisch saubere Möglichkeit, es am Anfang zu platzieren. Es ist auch bedauerlich, nicht allgemein genug zu sein, so dass Sie mit dem Hund beginnen, aber einfach einen anderen Dateinamen hinzufügen, wenn Sie möchten, dass er auch nach dem vorherigen verarbeitet wird. (Die >ist andererseits nicht halb so schlecht. Sie hat am Ende eine nahezu perfekte Platzierung. Sie ist normalerweise kein wiederverwendbarer Teil einer Pipeline und wird dementsprechend symbolisch unterschieden.)</edit>

Die nächste Frage ist, warum es wichtig ist, Befehle zu haben, die lediglich eine Datei ausspucken oder mehrere Dateien ohne weitere Verarbeitung zu stdout verketten. Ein Grund besteht darin, zu vermeiden, dass jeder einzelne Unix-Befehl, der auf der Standardeingabe ausgeführt wird, weiß, wie mindestens ein Befehlszeilenargument analysiert und als Eingabe verwendet wird, falls vorhanden. Der zweite Grund besteht darin, zu vermeiden, dass Benutzer sich Folgendes merken müssen: (a) wohin die Dateinamenargumente führen; und (b) den oben erwähnten stillen Pipeline-Fehler vermeiden.

Das bringt uns zu dem Grund, warum grepes die zusätzliche Logik gibt. Das Grundprinzip besteht darin, für Befehle, die häufig und eigenständig (und nicht als Pipeline) verwendet werden, eine flüssige Benutzerführung zu ermöglichen . Es ist ein leichter Kompromiss der Orthogonalität für einen signifikanten Gewinn an Benutzerfreundlichkeit. Nicht alle Befehle sollten auf diese Weise entworfen werden, und Befehle, die nicht häufig verwendet werden, sollten die zusätzliche Logik von Dateiargumenten vollständig vermeiden (denken Sie daran, dass zusätzliche Logik zu unnötiger Fragilität führt (die Möglichkeit eines Fehlers)). Die Ausnahme besteht darin, Dateiargumente wie im Fall von zuzulassen grep. (Übrigens, das lshat einen ganz anderen Grund, Dateiargumente nicht nur zu akzeptieren, sondern so ziemlich zu verlangen)

Schliesslich hätte man es besser machen können, wenn solche aussergewöhnlichen Befehle grep(aber nicht notwendigerweise ls) einen Fehler erzeugen, wenn die Standardeingabe verfügbar ist. Dies ist sinnvoll, da die Befehle Logik enthalten, die den orthogonalen Geist des allmächtigen Unix für die Benutzerfreundlichkeit verletzt. Zur weiteren Bequemlichkeit des Benutzers, dh zur Verhinderung des durch einen stillen Fehler verursachten Leidens, sollten solche Befehle nicht zögern, ihre eigene Verletzung zu verletzen, indem sie den Benutzer benachrichtigen, wenn die Möglichkeit eines stillen Fehlers besteht.


1
Wie auf dem Cross-Site-Duplikat dieser Antwort und Frage diskutiert, grep pattern f1 f2 f3ist keine einfache Verkettung . grepkennt sich mit Dateien aus und druckt Dateinamen (und optional Zeilennummern und was auch immer). grep . /sys/kernel/mm/transparent_hugepage/*ist ein netter Hack zum Drucken von Dateinamen: Dateiinhalt mit vielen einzeiligen Dateien. Das klassische Unix-Design ist, dass die meisten Dienstprogramme *.txtohne Notwendigkeit arbeiten cat. catDient zum Reduzieren mehrerer Dateien in einem Stream.
Peter Cordes

@PeterCordes Ich habe nicht so viel über grep geschrieben. Es gibt wesentliche Probleme, die ich in Bezug auf die Robustheit gegenüber Fehlern / Kopieren / Einfügen festgestellt habe. Korrektheit versus Leistung, die Sie bequemerweise zu Gunsten kleiner / peripherer Bedenken ignoriert haben.
Zufallsstring

Sie machen einige interessante und gültige Punkte, insbesondere zu den Fehlern, die beim Kopieren / Einfügen von Pipelines auftreten können. Ich würde vorschlagen, dass Sie Ihr grepBeispiel durch ein Programm wie cutdieses ersetzen , das keinen Grund hat, sich um mehrere Dateien zu kümmern, und das immer nur von seinem Standard gespeist werden kann. Einige Dienstprogramme trakzeptieren überhaupt keine Dateibegriffe und funktionieren nur als Filter. Sie haben also die Wahl zwischen catund <.
Peter Cordes

1
Mein größtes Problem bei Ihrem Beitrag ist, dass Sie die Eingabeumleitung nicht berücksichtigen. <file cmd1 | cmd2 >outist nicht wunderbar, gebe ich zu, aber es ist durchaus möglich, sich daran zu gewöhnen. Sie beschäftigen sich immer wieder spöttisch mit "dem Geist des allmächtigen Unix", was für mich total platt ist, weil es sich so anhört, als ob Sie entweder nicht so verstehen oder nicht so verstehen wollen, wie es die Unix-Designer wirklich dachten. Es ist in Ordnung, wenn Sie das Unix-Design nicht mögen, aber es ist nicht von Natur aus dumm. Ich bin mir nicht sicher, ob das Design des Betriebssystems älter ist als die Shell-Syntax und wie es sich entwickelt hat, aber ein zusätzliches catim Jahr 1970 war es wert, vermieden zu werden!
Peter Cordes

1
@PeterCordes Im Nachhinein war ich in meiner Antwort ziemlich umständlich, was vom wichtigsten Punkt ablenkt - Richtigkeit zuerst, Optimierung zweitens. Das Extra cathilft beim Wiederverwenden und Verbinden von Pipelines, während Sie ohne es stille Fehler erhalten können (suchen Sie in meiner Antwort nach "lautlos").
Randomstring

2

Zur Verteidigung der nutzlosen Verwendungen der Katze

(Ein paar Absätze, um den Tsunami der nörgelnden Kommentare gegen diese Praxis auszugleichen)

Ich benutze Bash seit zu vielen Jahren sowohl als Shell als auch als Skriptsprache für kleine Skripte (und manchmal bedauerlicherweise für nicht so kleine). Vor langer, langer Zeit habe ich etwas über den "Useless Use of Cat" (UUoC) gelernt. Mindestens jede Woche bin ich immer noch schuldig, aber ehrlich gesagt fühle ich mich selten ein bisschen gezwungen, es zu vermeiden. Ich glaube, dass es bei der Verwendung von catvs < filemehr um Geschmack als um technische Unterschiede geht, und ich habe diese Antwort geschrieben, um neue Linux-Benutzer zu schützen, die meinen Geschmack teilencatvon der Annahme, dass etwas ernsthaft falsch ist (und beachten Sie die wenigen Gelegenheiten, in denen es gibt). Wie Linus Torvalds glaube ich auch, dass Geschmack oft wichtiger ist als Können. Das bedeutet nicht, dass mein Geschmack besser ist als dein, aber es bedeutet, dass ich, wenn etwas schlecht schmeckt, es nicht tun werde, ohne etwas Wertvolles zu erlangen.

Es ist bereits offensichtlich, dass ich wie der Frageautor der Meinung bin, dass die Verwendung von cat sehr natürlich ist, wenn ich an einer REPL-ähnlichen Bash arbeite, bei der ich ein Problem untersuche, indem ich inkrementell komplexe Befehle konstruiere. Hier ist ein sehr typisches Beispiel: Ich habe eine Textdatei und weiß nicht viel darüber. Ich werde tippen cat file, um einen Eindruck vom Inhalt zu bekommen. Wenn der Ausgang ist zu viel werde ich meinen Pfeil getroffen und je nach den Umständen werde ich hinzufügen | headoder | grep foooder | what_evermeinen vorherigen Befehl erstreckt durch die Verarbeitungsschritte anhängen. Diese Art, schrittweise von einem einfachen Befehl zu einem komplexeren zu wechseln, indem ein Verarbeitungsschritt nach dem anderen hinzugefügt wird, fühlt sich für mich sehr natürlich an (ich mache dasselbe auf ipython und ich liebe die Art und Weise)pyfunctionalund ähnliche Programmierwerkzeuge umfassen diesen Stil). Wenn ich also an der Bash-Shell arbeite, bin ich zuversichtlich, dass cates sinnloser ist , meinen Fluss zu unterbrechen, um das zu entfernen, als es sein zu lassen und zu leiden ... na ja, in 99,9% der Fälle hat dies überhaupt keine Konsequenz.

Natürlich , wenn Schreiben von Skripts Dinge vielleicht ändern. Aber selbst wenn ich Skripte schreibe, ist es meine Meinung, dass Leute, die sich über UUoC lustig machen, diese wichtigen Lektionen mit großem Verstand ignorieren: "Vorzeitige Optimierung ist die Wurzel allen Übels" . Und wenn Sie nichts Atypisches tun, ist es für UUoC wirklich schwierig, einen Ort zu finden, an dem eine Optimierung erforderlich ist. Natürlich müssen Sie auf jeden Fall wissen, was daran ineffizient ist (dies ist übrigens der zusätzliche Prozessaufruf, da es nur wenige zu erwähnen scheinen). Mit diesem Wissen wissen Sie, was zu tun ist, wenn Sie auf seltenen Systemen arbeiten, auf denen das Aufrufen eines Prozesses teuer ist (z. B. bei einigen eingebetteten Systemen oder in geringerem Maße bei CygWin). Zum Beispiel, wenn Sie gerade anrufencatviele Male pro Sekunde in einer Schleife (BTW, wenn Sie sich in dieser Position befinden, fragen Sie sich, ob bash das richtige Werkzeug für den Job ist). Wieder aber: "Erst richtig arbeiten lassen, dann bei Bedarf optimieren" .

Und wie erklären Sie den Tsunami von Beschwerden über UUoC Nick?

Abgesehen davon, dass nicht jeder meinen Geschmack hat, glaube ich, dass ein Großteil der Gründe, warum sich so viele Menschen über UUoC beschweren, nicht technisch, sondern menschlich ist: Die meisten Unix-Neulinge kennen die < file commandRedewendung nicht und es ist verlockend, den "alten Guru" zu spielen " zu ihnen. Er wird auch die Möglichkeit haben, ausgefallene Wörter ("Prozessaufruf") zu verwenden und das Thema "Optimierung" anzusprechen. Ein guter Eindruck ist garantiert, daher ist es sehr schwer zu widerstehen. Dann werden die Neulinge den Rat des Gurus zum Nennwert nehmen und ihn für eine lange Zeit anderen als "Die einzige Wahrheit" wiedergeben (und diese Antwort herabstimmen :-). Witzige Anmerkung: Es ist wahrscheinlich so einfach, Bash zu reparieren, um Ineffizienzen von UUoC zu vermeiden, dass man sich fragen muss, warum niemand diese Funktion hinzugefügt oder gemacht hat< filenamecat eine datei nach so vielen jahren. Eine dunkle Seele würde vorschlagen, dass einige graubärtige Bash-Hacker Gelegenheiten lassen, uns zu verspotten ;-)


+1 Lieben Sie den letzten Absatz darüber, warum die anthropologischen Faktoren, die diese Praxis verbreiten :-)
Zufallszeichenfolge

1

Was wirklich schön wäre, ist eine Shell, die folgende Syntax unterstützt:

< filename cmd | cmd2 cmd2arg1... | cmd3

In der Zwischenzeit halte ich das für cat filename | realcmd1...akzeptabel, da die Syntax mit anfänglichen Befehlen standardisiert bleibt, die den Dateinamen als Argument erfordern.


17
Bash und ähnliche Shells unterstützen < filename cmd | cmd2 .... Ist das nah genug?
Garyjohn

@garyjohn: Ich denke du solltest das als Antwort posten.
Kevin Reid

14
Obligatorischer alter Shell-Hacker-Kommentar: Bourne-artige Shells haben das < file command ...zumindest seit Mitte der 80er Jahre und wahrscheinlich schon in den 70er Jahren unterstützt, als das Original shgeschrieben wurde. Im Allgemeinen werden E / A-Umleitungen von links nach rechts analysiert und können in der Befehlszeile in beliebiger Reihenfolge eingefügt werden. Also, cmd <file arg arg...wäre auch gültig.
Dale Hagglund

3
Ja, es liegt zum Teil daran, wie einfach es ist zu tippen, dass ich das UUOC erfunden habe.
Randal Schwartz

2
Ein verschobener Buchstabe gegen vier verschobene ist kein so großer Unterschied, und ich möchte lieber einen zusätzlichen Vorgang auslösen, den selbst mein Telefon kaum bemerkt, als eine Datei in meine Eingabeaufforderung zu leiten, die mir jedes Mal Kopfschmerzen bereitet, wenn ich sie sehe .
Aaron Miller

0

Für alle, die sagen, dass die Verwendung von Katzen akzeptabel ist, weil sie besser riechen oder besser lesbar sind, würde ich nur Folgendes sagen:

Für Sie vielleicht ... aber nicht für andere, die Ihren Code lesen oder versuchen, ihn zu verstehen. Wenn Sie niemals versuchen werden, andere mit Ihren Beispielen zu unterweisen oder Ihren Code zu teilen, verwenden Sie ihn auf jeden Fall nach Belieben.

Ich werde auch diesen Kommentar hinzufügen, da Linux-Benutzer und Administrator / Ingenieur lange Zeit ... (und es gibt viele von uns), dass es unsere Augen bluten lässt, dies zu sehen. Warum? Weil es Ressourcen auf Systemen verwendet, auf denen wir Ressourcen streng kontrollieren. Der Befehl cat und die Pipe selbst verwenden zusätzlichen Speicher und Dateihandles, die völlig unbrauchbar sind. Sie haben Ressourcen gebunden, die mein System kostenlos benötigt, und Sie haben NICHTS gewonnen, das die Verwendung dieser Ressourcen erklären kann. Das ist ein riesiges Nein, nein.

Jetzt kann ich den ganzen Tag hier sitzen und mit jedem über Dinge wie Code-Geruch oder Lesbarkeit diskutieren, aber am Ende des Tages ist es eine Frage des Schreibens oder Falsches und jedes Mal, wenn Sie Ressourcen auf einem System nutzen und nichts dafür bekommen ... es ist falsch.

Als Heimanwender können Sie aus meinen Ratschlägen lernen und lernen, wie man Dinge besser macht, oder Sie können wählen, ob Sie vom "Geruch" der Katzen, Ihrer Wahl, geblendet werden möchten Wenn Sie diese Übung die ganze Zeit machen, müssen Sie stillschweigend zugeben, dass sie richtig sind und dass Sie hartnäckig sind, weil es wahr ist. :-)


Ich bin auch ein langjähriger Linux (und früher * nix) Benutzer und Softwareentwickler. Sie sprechen nicht für mich, wenn Sie sagen, dass "es unsere Augen bluten lässt", um zu sehen cat foo.txt | .... Die andere Antwort erklärt gut, warum es eine gute Verwendung sein kann. Die einfache Zusammenfassung des Falls lautet: "$ CPU time << $ Brain time" (wie @MikeP oben kommentiert).
Jim DeLaHunt

Erstens war das eine Antwort aus dem Jahr 2017 (ein Weg, um die Toten wiederzubeleben). Zweitens sollten wir uns als Administrator oder Entwickler stets bemühen, den Ressourcenverbrauch so gering wie möglich zu halten. Versuchen Sie beim Schreiben von Apps und Diensten, auf Speicher- oder CPU-Ausfälle zu achten, die der App / dem Dienst keinen oder nur geringen Nutzen bringen. Nun, UUOC ist genau das. Nun, ich bin sicher, es gibt absolut gültige Verwendungen von Katze, bei denen es um das Leiten von Befehlen geht ... nur nicht oft. Ich spreche also vielleicht nicht für Sie, wie Sie sagen ... aber wenn Sie ein Profi sind, würde ich mich fragen, warum Sie nicht eher zustimmen (unter der Voraussetzung eines echten UUOC-Szenarios).
David Dreggors

Das Problem ist, dass Speicher- oder CPU-Ausfälle nicht die einzigen Kosten sind, die ein Entwickler für die Optimierung benötigt. Die Zeitkosten für das Verständnis des Problems sowie das Schreiben und Debuggen einer Implementierung sind ebenfalls Teil des Kompromisses. Einige der Antworten hier basieren auf der Einschätzung, dass die menschliche Zeit viel knapper und teurer ist als Speicher oder CPU. . … Aber dies wird zu einer Diskussion, die gegen die Regeln verstößt. Lassen Sie die Stimmen zu den Antworten für die Perspektive sprechen, die von Super Usern gebilligt wird.
Jim DeLaHunt
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.