Katzenbefehl und Echo

13

Ich möchte die Ausgabe von Echo mit dem Inhalt einer Datei verketten. Ich habe den folgenden Befehl ausprobiert:

echo "abc" | cat 1.txt > 2.txt

Die 2.txtDatei enthält jedoch nur den Inhalt von 1.txt. Warum funktioniert es nicht?

Ringger81
quelle
3
Programme catlesen nur gerne von der Standardeingabe, wenn sie keine Dateinamenargumente haben.
Barmar

Antworten:

23

Es funktioniert nicht, weil das catProgramm in Ihrer Pipe-Sequenz nicht angewiesen wurde, die echoProgrammausgabe von der Standardeingabe zu lesen .

Sie können -einen Pseudodateinamen verwenden, um die Standardeingabe anzugeben cat. Ab man cateiner msys2-Installation:

EXAMPLES
       cat f - g
              Output f's contents, then standard input, then g's contents.

Also versuche

echo "abc" | cat - 1.txt > 2.txt

stattdessen.

mvw
quelle
20

Wie von anderen angemerkt, schlägt Ihr ursprünglicher Befehl fehl, weil cat 1.txtseine Standardeingabe ignoriert wird. Geben Sie entweder an, dass es das erste Argument ( cat - 1.txt) sein soll, oder verwenden Sie die Blockumleitung , um echo abc und cat 1.txt zusammen umzuleiten . Nämlich:

{ echo abc; cat 1.txt; } > 2.txt 

Relevanter Auszug aus dem Handbuch ( man bash):

Zusammengesetzte Befehle
Ein zusammengesetzter Befehl ist einer der folgenden. In den meisten Fällen kann eine Liste in der Beschreibung eines Befehls durch eine oder mehrere Zeilenumbrüche vom Rest des Befehls getrennt sein, gefolgt von einer neuen Zeile anstelle eines Semikolons.

(aufführen)

    Die Liste wird in einer Subshell-Umgebung ausgeführt (siehe COMMAND EXECUTION ENVIRONMENT unten). Variablenzuweisungen und integrierte Befehle, die sich auf die Umgebung der Shell auswirken, bleiben nach Abschluss des Befehls nicht wirksam. Der Rückgabestatus ist der Beendigungsstatus der Liste.

{aufführen; }

    list wird einfach in der aktuellen Shell-Umgebung ausgeführt.  Die Liste muss mit einem Zeilenumbruch oder einem Semikolon abgeschlossen werden. Dies wird als Gruppenbefehl bezeichnet . Der Rückgabestatus ist der Beendigungsstatus der Liste . Beachten Sie, dass im Gegensatz zu dem Meta - Zeichen (und ), {und }sind reservierte Worte und muß dort auftreten , wo ein reserviertes Wort erkannt werden darf. Da sie keinen Wortumbruch verursachen, müssen sie durch Leerzeichen oder ein anderes Shell-Metazeichen von der Liste getrennt werden .

Die erste Option (Subshell-Umgebung) hat eine Reihe von Nebenwirkungen, von denen die meisten, wenn nicht alle, für Ihr Szenario irrelevant sind. Wenn Sie jedoch nur die Ausgabe einer Reihe von Befehlen umleiten möchten, wird Option 2 hier (Gruppenbefehl) bevorzugt.

Nubarke
quelle
6
( echo "abc"; cat 1.txt ) > 2.txt

Sie haben die Echoausgabe an cat weitergeleitet, aber cat hatte keine Verwendung für die Eingabe und hat sie ignoriert. Jetzt werden die Befehle nacheinander ausgeführt und ihre Ausgabe wird gruppiert (die Klammern) und in 2.txt geleitet.

Gerard H. Pille
quelle
1
Diese Antwort kann verbessert werden, indem erklärt wird, wie es funktioniert und warum der ursprüngliche Versuch des OP nicht funktioniert.
Bob
OK, habe es versucht.
Gerard H. Pille
5
Eine Unterschale ist hier nicht ausdrücklich erforderlich, vielleicht ist es besser, einen Gruppenbefehl zu verwenden. Siehe meine Antwort für weitere Details.
Nubarke
Ah, aber ich würde niemals Bash verwenden.
Gerard H. Pille
1
@ GerardH.Pille: Während Daniels Antwort zitiert bash(1), beschreibt sie das Verhalten, das jede POSIX-kompatible Shell unterstützen muss.
G-Man sagt "Reinstate Monica"
2

Ihr Befehl cat 1.txtmacht nichts mit der Ausgabe von echo "abc".

Stattdessen: (echo "abc"; cat 1.txt) > 2.txt schreibt die Ausgabe beider Befehle in 2.txt.

Muclux
quelle
Diese Antwort kann verbessert werden, indem erklärt wird, wie die vorgeschlagene Alternative funktioniert.
Bob
1

In jeder POSIX-Shell können Sie die Befehlssubstitution cat fileals Eingabe für Folgendes verwenden echo:

echo $(cat file1.txt) "This Too"

In Bash können Sie die Prozessersetzung verwenden und echo als eine andere "Datei" verwenden cat, wie in:

cat file1.txt <(echo This Too)

und leiten Sie die Ausgabe dann nach Belieben weiter oder leiten Sie sie um.

Wie jede andere Antwort sagt, ignoriert Katze stdin, wenn sie eine Datei zum Anschauen hat. (Ich mag auch die Antworten von Daniel & mvw, +1 für sie)

Xen2050
quelle
1
Diese Antwort kann verbessert werden, indem erklärt wird, warum der ursprüngliche Versuch des OP nicht funktioniert (und warum dies stattdessen erforderlich ist).
Bob
1
Die <(command)Konstruktion ist eine Bash-Erweiterung. Es ist kein POSIX, daher können Sie sich in Skripten, mit denen ausgeführt werden soll, nicht darauf verlassen /bin/sh.
Rhialto unterstützt Monica
0

Nur eine Vermutung, aber es sieht so aus, als hätten Sie einen wiederholbaren Prozess, der ein guter Kandidat für einen Alias ​​oder eine Funktion ist. Aliase sind normalerweise Abkürzungen zum Aufrufen von Bash-Befehlen, wie z. B. Abkürzung, für einen einzelnen Eingabestream als Argument.

alias hg="history | grep"

In diesem Fall wäre eine Funktion jedoch besser lesbar, da Sie mehrere diskrete (2) Eingabestreams sowie mehrere Bash-Befehle kombinieren. Sie haben zwei Argumente, das erste ist eine Zeichenfolge und das andere ein Dateipfad. Am Ende möchten Sie, dass das Ergebnis in den Standardausgabestream geschrieben wird.

Geben Sie an einer CLI-Eingabeaufforderung Folgendes ein:

# ecat()        
{
echo ${1}
cat ${2}
}

Ihre Funktion heißt ecat, was unvergesslich ist.

Jetzt können Sie als aufrufen

ecat "abc" 1.txt

Geben Sie zum Anhängen einfach ein anderes Ausgabeziel an stdout an:

ecat "abc" 1.txt >> 2.txt

Der Append-Umleitungsoperator '>>' fügt die Ausgabe am Ende der angegebenen Datei hinzu.

Wenn es Ihnen gefällt, hängen Sie es zur Wiederverwendung an Ihre ~ / .bashrc-Datei an.

declare -f ecat >> ~/.bashrc

Das bedeutet auch, dass Sie innerhalb Ihrer Funktionsdefinition usw. dekorieren können.

Auch eine gute Idee, um Dateien vor dem Überschreiben zu schützen, indem Sie diese zu Ihrem ~ / .bashrc hinzufügen

set noclobber
FrDarryl
quelle
2
Damit sich Ihre Funktion richtig verhält, sollten Sie "$1"und verwenden "$2". In diesem Zusammenhang nützen die geschweiften Klammern nichts. Siehe ${name}bedeutet nicht , was Sie denken , es tut ... .
G-Man sagt "Reinstate Monica"
1
Wie reagiert der noclobberVorschlag auf die vorliegende Frage? (Ich bin auch nicht sehr davon überzeugt, dass es ein guter Rat ist - das Ändern des globalen Verhaltens führt dazu, dass Skripte / Ratschläge / Praktiken, die unter Berücksichtigung der Standardeinstellungen erstellt wurden, beschädigt werden.)
Charles Duffy
0

Der folgende Code funktioniert auch:

echo abc >> 1.txt && cat 1.txt > 2.txt

Die Ausgabe von echo abc wird mit >> an 1.txt angehängt. Danach weist das && an, den nächsten Befehlssatz auszuführen, der 1.txt enthält, und gibt ihn dann an 2.txt aus . Grundsätzlich hängt es die Ausgabe des ersten Befehls an 1.txt an und sendet dann die Ausgabe von 1.txt an 2.txt.

Wenn der abc zuerst angezeigt werden soll, können Sie den folgenden Code verwenden:

echo abc >> 2.txt && cat 1.txt >> 2.txt
Nasir Riley
quelle
1
Dies wird (1) abcam Ende von setzen 2.txt; Die Frage will es ganz oben. (2)  die Datei ändern1.txt ; das ist inakzeptabel.
G-Man sagt "Reinstate Monica"
Wo steht das? Ringger81 hat nie angegeben, wo in 2.txt abc erscheinen soll. Sie gehen von Dingen aus, die in der Frage niemals stehen.
Nasir Riley
(1) OK, Sie erhöhen einen gültigen Punkt auf # 1. Während die Frage im Text "Ausgabe vom Echo" vor "Inhalt einer Datei" erwähnt und dann den Befehl " echovor dem Beispiel" catin den Beispielbefehl einfügt, wird vermutlich nie genau explizit angegeben , dass die Ausgabe vom Echo vor dem Inhalt der Eingabedatei. Es scheint nur, dass die meisten Leute es so interpretierten. (2)  1.txtist eine Eingabedatei. Die Frage sagt nichts über das Ändern aus 1.txt. Die Tatsache, dass Eingabedateien nicht geändert werden sollten, versteht sich von selbst.
G-Man sagt "Reinstate Monica"
Ich kann Ihren Standpunkt verstehen, die Imput-Datei nicht zu ändern. Mein zweiter Code erzielt den gewünschten Effekt, ohne dies zu tun.
Nasir Riley
1
Öffnen einer Datei, Anhängen, Schließen , erneutes Öffnen, erneutes Anhängen ... Warum tun Sie das, anstatt sie nur einmal zu öffnen und die Umleitung für beide Vorgänge beizubehalten?
Charles Duffy