Leiten Sie die Ausgabe aller Befehle in die Datei um, nicht nur in die letzte

11

Ich möchte einer Datei mit Echo einen Header hinzufügen und dann mit einem Befehl den Rest der Datei erstellen. Dies bedeutet, dass ich zwei separate Befehle verwenden werde.

Wie schreibe ich die Ausgabe beider Befehle in eine Datei mit Umleitung?

ich habe es versucht

echo "header line" | cut -c 1-5 input_file > output_file

echo "header line"; cut -c 1-5 input_file > output_file

Dadurch wird nur die Ausgabe des Befehls cut umgeleitet.

Der folgende Befehl funktioniert, fühlt sich aber ungeschickt an:

echo "header line" > output_file; cut -c 1-5 input_file >> output_file

Was ist die clevere Art, mein Problem zu lösen?

Die Unfun Cat
quelle

Antworten:

11

Das Problem hier ist kein Problem mit der Linux-Umleitung. Vielmehr handelt es sich um ein grundlegendes Missverständnis der Funktionsweise der Pipeline. Die Umleitung funktioniert hier nicht, da nur der Schnitt tatsächlich auf Standard gedruckt wird. stdout für den Befehl echo wurde an das stdin von cut weitergeleitet (das in diesem Fall nicht verwendet wird, da eine Datei angegeben ist).

echo "header line" > output_file && cut -c 1-5 input_file >> output_file

ist das, was Sie wollen, und überhaupt nicht unelegant (ich habe Ihren ;durch ersetzt, &&damit der Befehl cut nur ausgeführt wird, wenn der Header erfolgreich geschrieben wurde; auf diese Weise wird er nicht ausgeführt, wenn Sie keine Berechtigungen zum Erstellen oder Schreiben in output_file haben ).

Sie können alles auch in einer Subshell ausführen, z.

(echo "header line"; cut -c 1-5 input_file) > output_file

Dies hat jedoch keinen wirklichen Vorteil. Bei komplexeren Beispielen kann dies zu Problemen führen, wenn Sie nicht mit dem Umfang der Subshell vertraut sind.

Wenn Sie möchten, dass cut stdin an stdout weiterleitet, können Sie Folgendes versuchen:

echo "header line" | cut -c 1-5 - input_file

(Der Bindestrich ist eine gebräuchliche Verknüpfung für stdin)

Dies führt jedoch auch die Schnittoperation für stdin aus (was zu einer Kopfzeile von "Kopfzeile" führt). Es ist schwer zu sagen, ob dies das ist, was Sie wollen oder nicht.

Sam Whited
quelle
13

Was Sie suchen ist:

{ echo "header line"; cut -c 1-5 input_file; } > output_file
  • Diese Syntax hat keine Nebenwirkungen, da die Befehle in der aktuellen Shell ausgeführt werden, nicht in einer Subshell
  • Es gibt eine klare Abgrenzung der Befehle, die in die Ausgabedatei gehen
  • Es lässt sich gut skalieren, da Sie es folgendermaßen umschreiben können:

{
  echo "header line"
  cut -c 1-5 input_file
  ... # insert new commands here
} > output_file

Wenn die Fehlerausgabe in dieselbe Datei verschoben werden soll, können Sie die letzte Zeile folgendermaßen ändern:

} > output_file 2>&1

Vielen Dank an Olivier Dulac für die Erinnerung an diesen Tipp.

Wenn Sie möchten, dass eine Ausgabe innerhalb des Blocks auf Ihren Bildschirm gelangt, können Sie die folgende Syntax verwenden:

{
  echo "header line"
  echo "this line doesn't go to output_file" > /dev/tty
  cut -c 1-5 input_file
} > output_file
jlliagre
quelle
+1: Es ist klarer und identifiziert klar, was wohin umgeleitet wird. So leiten Sie alles (einschließlich Fehler msg): { .... } > some_file 2>&1(wird „clobber“ irgendeine_Datei nicht clobber, aber append , um es stattdessen nur das zu ändern. >In a >>: { ... } >> some_file 2>&1)
Olivier Dulac
4

Nur um die Antworten abzurunden, gibt es exec.

exec > output_file
echo "header line"
cut -c 1-5 input_file
hildred
quelle
+1: In Skripten ist es sehr üblich, dies zu verwenden (weniger in der Befehlszeile, da die Dinge verwirrend werden ^^)
Olivier Dulac
Könnte jemand diese Lösung näher erläutern? Ich kann sehen, was es tut, aber ich verstehe 'exec' in diesem Zusammenhang nicht. Es sieht auch so aus, als müssten Sie etwas wieder ausschalten, wenn der Rest Ihres Skripts normales Standardout benötigt.
Joe
1
Wenn Sie exec in einem Skript ohne Befehl verwenden, können Sie eine E / A-Umleitung für exec ausführen, die sich auf die aktuelle Shell und alle zukünftigen untergeordneten Elemente auswirkt.
Hildred
Vielen Dank. Das habe ich noch nie gesehen. Ich denke, es wird sehr nützlich sein.
Joe