Wie leite ich die Ausgabe eines Befehls in eine Datei um, wenn der Befehl Benutzereingaben auffordert?

7

Ich habe einen Befehl, der den Benutzer zur Eingabe einiger Eingaben auffordert und das Ergebnis dann an das Terminal ausgibt. Ich habe den folgenden Befehl eingegeben, um die Ausgabe in eine Datei umzuleiten:

$the_command > abc.txt

Aber es funktioniert nicht. Das Problem ist, dass es keine Eingabeaufforderung gibt. Der Text dieser Eingabeaufforderungsfragen wird in die Datei abc.txt ausgegeben, nicht das gewünschte Ergebnis.

Aaron Shen
quelle

Antworten:

3

Ihr Befehl funktioniert und leitet die Ausgabe ordnungsgemäß in die Datei um abc.txt.
Die Frage ist, wie Ihr Skript die Eingabedaten fragt und wie Sie das Skript ausführen.
Lassen Sie uns mit zwei Beispielen sehen:

# Script_1.sh                                     # 1
echo Please, enter your firstname and lastname    # 2
read FN LN                                        # 3
echo "Hi! $LN, $FN !"                             # 4

und

# Script_2.sh                                     # 5
read -p "Enter a comment " CM                     # 6
echo  "You said $CM"                              # 7

Wenn Sie laufen /bin/bash Script1.sh > abc.txt, wird die Frage "Bitte eingeben ..." auf Ihrem tty nicht angezeigt. Wenn Sie die erwartete Eingabe über die Tastatur geben, finden Sie die Ausgabe der Zeilen 2 und 4 in Ihrer abc.txtDatei.

Wenn Sie ausführen /bin/bash Script2.sh > abc.txt, wird die Frage "Kommentar eingeben" angezeigt, in der abc.txtDatei wird jedoch nur die Ausgabe der Zeile 7 angezeigt.

Hinweis: Wenn Sie Script2 ausführen, sh in einer Subshell

(bash Script2.sh 2>&1)> abc.txt

Sie werden keine Ausgabe auf tty sehen und Sie werden alle in der abc.txtDatei finden.
Wenn Sie es mit ausführen

bash Script2.sh 2>ccc.txt 1>ddd.txt`

Sie finden die Standardausgabe (Zeile 7) in ddd.txtund den Standardfehler (Zeile 6) in ccc.txt.


Wenn Sie nur einen Teil Ihrer Befehlsausgabe umleiten möchten , müssen Sie Ihr Skript ändern.
Eine Möglichkeit besteht darin, eine Funktion zu erstellen, mit der der Teil des Skripts verschoben werden kann, der die interessante Ausgabe generiert (siehe unten). Anschließend können Sie diese Funktion über den Hauptteil Ihres Skripts (wo ursprünglich der Code war, den Sie in die Funktion verschoben haben) aufrufen und nur diese Ausgabe in die Protokolldatei umleiten:

 Part_To_Redirect(){
     : # all that you want
 }

 # ... Main part of the script
 # point where it was the part that generates the output
 Part_to_Redirect "$@" > abc.txt   # this to store only that part in the file
 # Part_to_Redirect "$@" >> abc.txt  # this to append that part in the file
 # ...

Sie sollten auch nützlich finden , teedass

Leitet die Ausgabe in mehrere Dateien um, kopiert die Standardeingabe in die Standardausgabe und auch in alle als Argumente angegebenen Dateien.

 the_command  | tee abc.txt       # To redirect Standard output
 or 
 the_command 2>&1 | tee abc.txt   # To redirect err in out and both in the file

In diesem Fall haben Sie die normalen Ausgaben Ihres Befehls auf dem tty, aber gleichzeitig speichern Sie eine Kopie in der Protokolldatei abc.txt. In Ihrem Fall sollte es gemütlich sein, wenn Sie read -pden Aufruf wie im Skript2 verwenden the_command | tee abc.txt.

Anmerkungen und Referenzen:

Durch Hinzufügen können "$@"Sie alle Argumente Ihres Skripts an die Funktion übergeben.

Es kann interessant sein, mehr über die Basisrichtung aus vielen Quellen im Internet zu lesen.

Hastur
quelle
Ich glaube, was sind die Steuerungs- und Umleitungsoperatoren der Shell? ist eine bessere Referenz.
Scott
@ Scott, kostbar wie immer. Es gibt so viele Quellen im Internet, dass es heutzutage schwierig ist, nur eine auszuwählen, die Ihren Anforderungen entspricht, insbesondere wenn Sie die Person nicht kennen (ich meine das OP).
Hastur
Nun, der Punkt ist, dass ich Sie auf unsere Referenz hingewiesen habe . Außerdem musste ich nur einen Blick auf Ihre beiden werfen, um Ungenauigkeiten und schlampiges Schreiben zu finden. ("kostbar wie immer"?)
Scott
@ Scott: Was mochtest du nicht wertvoll oder üblich ? Wir treffen uns hier in wenigen Tagen zweimal und Ihre beiden Kommentare haben mir geholfen, eine bessere Antwort zu finden ... und dies hat Sie ohne Beleidigung "wertvoll wie immer" gemacht . :-)
Hastur
1
OK; "kostbar" kam mir vor, aber ich denke, das ist eine tertiäre Bedeutung.
Scott
3

Standardmäßig wird nur STDOUTumgeleitet und / oder weitergeleitet. Was Sie wollen, ist in STDOUTRuhe zu lassen und alles, was über STDINweitergeleitet wird, umzuleiten.

Wenn das Bearbeiten the_commandeine Option ist, können Sie sicherstellen, dass die Frage STDERRstattdessen ausgegeben wird (das sollte sie unabhängig von Weiterleitungen auf dem Bildschirm ablegen), und sie dann wiedergeben lassen, was auch immer der Benutzer über auf den Bildschirm zurücktippt STDOUT.

Jarmund
quelle
1
STDERRsollte es unabhängig von Weiterleitungen auf dem Bildschirm ablegen Nein. Wenn Sie umleiten 2>xyz, wird stderr ebenfalls umgeleitet. Es kann jedoch ein Programm geöffnet und verwendet werden /dev/tty, das das steuernde Terminal unabhängig von Umleitungen verwendet.
glglgl
@glglgl Ich habe ein paar Programme gesehen, die darauf bestanden, /dev/tty/direkt damit zu arbeiten, und sie waren ziemlich nervig. Sie nehmen keine Eingaben entgegen STDIN, verschmutzen Ihr Terminal weiterhin und sind sehr überrascht, wenn sie ohne Terminal laufen.
Joker_vD
1

Normalerweise gibt es zwei wichtige Ausgabeleitungen: STDOUT(für die reguläre Ausgabe) und STDERR(für Fehlermeldungen).

Das Problem hierbei ist, dass sowohl die "reguläre" Ausgabe des Befehls als auch der Text der Eingabeaufforderung geschrieben werden STDOUT, sodass sie immer an derselben Stelle abgelegt werden. Wenn Sie Ihre Umleitung verwenden, wird nur das Ganze STDOUTeinschließlich der Eingabeaufforderung benötigt.

Wenn das Umschreiben (wie in einer anderen Antwort von Jarmund vorgeschlagen) des Befehls nicht möglich ist, verfügt der Befehl möglicherweise über eine zusätzliche Option / ein zusätzliches Flag (wie --output), mit dem eine Ausgabedatei angegeben werden kann, anstatt die Umleitung zu verwenden.

Slizzered
quelle