Wie kann ich die Konsolenausgabe in einem Bat-Skript wiedergeben und an eine Datei senden?

136

Ich habe ein Batch-Skript, das eine Aufgabe ausführt und die Ausgabe an eine Textdatei sendet. Gibt es eine Möglichkeit, die Ausgabe auch im Konsolenfenster anzuzeigen?

Beispielsweise:

c:\Windows>dir > windows-dir.txt

Gibt es eine Möglichkeit, die Ausgabe der dirAnzeige im Konsolenfenster anzuzeigen und in die Textdatei einzufügen?

JamesEggers
quelle
Hier werden die Weiterleitungen erklärt, die Sie vornehmen können, und einige Beispiele. <br> Hoffe, es hilft :)
emoSTN
Bitte beachten Sie, @Vadzim, dass eine Frage, die am 2. Februar 2009 um 16:38 Uhr gestellt wurde, nicht als Duplikat einer Frage angesehen werden kann, die fast drei Monate später am 28. April 2009 um 06:32 Uhr gestellt wurde.
Compo

Antworten:

216

Nein, Sie können nicht mit reiner Umleitung.
Aber mit ein paar Tricks (wie tee.bat ) kannst du.

Ich versuche die Umleitung ein wenig zu erklären.

Sie leiten einen der zehn Streams mit > Datei oder <Datei um.
Es ist unwichtig, ob die Umleitung vor oder nach dem Befehl erfolgt, sodass diese beiden Zeilen nahezu identisch sind.

dir > file.txt
> file.txt dir

Die Umleitung in diesem Beispiel ist nur eine Verknüpfung für 1> . Dies bedeutet, dass der Stream 1 (STDOUT) umgeleitet wird.
Sie können also jeden Stream umleiten, indem Sie die Nummer 2> err.txt voranstellen. Außerdem können Sie mehrere Streams in einer Zeile umleiten.

dir 1> files.txt 2> err.txt 3> nothing.txt

In diesem Beispiel wird die "Standardausgabe" in files.txt gespeichert, alle Fehler werden in err.txt gespeichert und stream3 wird in nothing.txt gespeichert (DIR verwendet den Stream 3 nicht).
Stream0 ist STDIN
Stream1 ist STDOUT
Stream2 ist STDERR
Stream3-9 werden nicht verwendet

Aber was passiert, wenn Sie versuchen, denselben Stream mehrmals umzuleiten?

dir > files.txt > two.txt

"Es kann nur einen geben", und es ist immer der letzte!
Es ist also gleich dir> two.txt

Ok, es gibt eine zusätzliche Möglichkeit, einen Stream zu einem anderen Stream umzuleiten.

dir 1>files.txt 2>&1 

2> & 1 leitet stream2 zu stream1 um und 1> files.txt leitet alle zu files.txt um .
Die Reihenfolge ist hier wichtig!

dir ... 1>nul 2>&1
dir ... 2>&1 1>nul

sind anders. Die erste Zeile leitet alle (STDOUT und STDERR) an NUL weiter,
die zweite Zeile leitet die STDOUT an NUL und STDERR an die "leere" STDOUT weiter.

Als eine Schlussfolgerung ist es offensichtlich, warum die Beispiele von Otávio Décio und andynormancx nicht funktionieren können.

command > file >&1
dir > file.txt >&2

Beide versuchen zweimal, stream1 umzuleiten, aber "Es kann nur einen geben", und es ist immer der letzte.
Also verstehst du

command 1>&1
dir 1>&2

Und im ersten Beispiel ist die Umleitung von Stream1 zu Stream1 nicht zulässig (und nicht sehr nützlich).

Ich hoffe es hilft.

jeb
quelle
24
So ist es unmöglich mit nativer Windows-Shell
fantastisch
7
@fantastory Es ist möglich, diese großartige Lösung von Dbenham Windows Batch zu sehen: 'tee' Befehl
jeb
97
Ich kann nicht glauben, dass ich gerade diesen ganzen Beitrag gelesen habe, um herauszufinden, dass das Ganze als "Nein" zusammengefasst werden kann.
Charles McKelvey
1
Was ist mit dem zweiten Mechanismus "Duplizierung behandeln"? Ich habe mit experimentiert 3<&2(beachte den LT anstelle des GT) und dann 3>errors.txt. Dies endete jedoch schlecht - alle nachfolgenden stderr-Ausgaben wurden erfasst errors.txt( dh auch von anderen Befehlen!).
Tomasz Gandor
Sie könnten aber verwenden for /f "delims=" %%v in ('dir') do echo %%v>>file.txt.
scriptmastere02
32

Verwenden Sie einfach die Windows-Version des UNIX-Befehls tee (zu finden unter http://unxutils.sourceforge.net ) auf folgende Weise:

mycommand > tee outpu_file.txt

Wenn Sie auch den STDERR-Ausgang benötigen, verwenden Sie Folgendes.
Das 2>&1kombiniert die STDERR-Ausgabe in STDOUT (dem primären Stream).

mycommand 2>&1 | tee output_file.txt
atn
quelle
3
Das PowerShell Tee-Object bietet ähnliche Funktionen. Get-Process | Tee-Object-Datei c: \ scripts \ test.txt
Kevin Obee
Ich habe dies sowohl in der Powershell als auch in der regulären Shell versucht. 1>tee a.txtleitet stdout in eine Datei mit dem Namen um, teeanstatt den teeBefehl aufzurufen . Kann jemand bestätigen, dass diese Antwort für sie funktioniert?
Mafu
@mafu Ich kann das bestätigen.
Cerno
@mafu Die obige Antwort ist leicht falsch. Sie müssen die Pipe "|" verwenden anstelle des ">" im oberen Beispiel. Seltsamerweise wurde in diesem Fall die Reihenfolge der STDOUT- und STDERR-Ausgabe in der Befehlszeile verwechselt. Das untere Beispiel funktioniert jedoch perfekt für mich.
Cerno
Auch der SourceForge-Download war für mich kaputt. Ich habe hier einen alternativen Host gefunden: wzw.tum.de/public-html/syring/win32/UnxUtilsDist.html (Universität München)
Cerno
9

Wenn Sie die Ausgabe nicht in Echtzeit benötigen (dh während das Programm sie schreibt), können Sie sie hinzufügen

type windows-dir.txt

nach dieser Zeile.

Mark Pim
quelle
oder in derselben Zeile (nützlich an der Eingabeaufforderung) : dir > windows-dir.txt & type windows-dir.txt. Dies gilt auch für Bausteine ​​: ( echo %date% <NL> echo %username% <NL> echo %time% <NL> pause>CON )>test.txt & type test.txt. Wenn die Ausgabe jedoch in Echtzeit benötigt wird, können Sie zB einen Windows-Port des Tee- Tools dafür verwenden ...
Maus
7

Die Lösung, die für mich funktioniert hat, war: dir> a.txt | Geben Sie a.txt ein .

NSPKUWCExi2pr8wVoGNk
quelle
2
Dies funktioniert mit Befehlen mit geringer Ausgabe. Mit einem großen Ausgabebefehl funktioniert es nicht, da nur der erste Puffer angezeigt wird. Er fordert eine Echtzeitausgabe an, während die Ausgabe in einer Protokolldatei gespeichert wird.
NetVicious
Es wäre problematisch, wenn Sie >> anstelle von>
Nime Cloud
6

Ja, es gibt eine Möglichkeit, eine einzelne Befehlsausgabe auf der Konsole (Bildschirm) und in einer Datei anzuzeigen. Verwenden Sie anhand Ihres Beispiels ...

@ECHO OFF
FOR /F "tokens=*" %%I IN ('DIR') DO ECHO %%I & ECHO %%I>>windows-dir.txt

Ausführliche Erklärung:

Der FORBefehl analysiert die Ausgabe eines Befehls oder Textes in eine Variable, auf die mehrfach verwiesen werden kann.

Schließen Sie für einen Befehl, wie z. B. DIR /Bin einfache Anführungszeichen ein, wie im folgenden Beispiel gezeigt. Ersetzen Sie den DIR /BText durch den gewünschten Befehl.

FOR /F "tokens=*" %%I IN ('DIR /B') DO ECHO %%I & ECHO %%I>>FILE.TXT

Schließen Sie zum Anzeigen von Text Text in doppelte Anführungszeichen ein, wie im folgenden Beispiel gezeigt.

FOR /F "tokens=*" %%I IN ("Find this text on console (screen) and in file") DO ECHO %%I & ECHO %%I>>FILE.TXT

... und mit Zeilenumbruch ...

FOR /F "tokens=*" %%I IN ("Find this text on console (screen) and in file") DO (
  ECHO %%I & ECHO %%I>>FILE.TXT
)

Wenn Sie Zeiten haben, in denen die Ausgabe nur auf der Konsole (Bildschirm) und zu anderen Zeiten nur an eine Datei und zu anderen Zeiten an beide gesendet werden soll, geben Sie die "DO" -Klausel der FOR-Schleife mithilfe einer Variablen an, wie unten mit gezeigt %TOECHOWHERE%.

@ECHO OFF
FOR %%I IN (TRUE FALSE) DO (
  FOR %%J IN (TRUE FALSE) DO (
    SET TOSCREEN=%%I & SET TOFILE=%%J & CALL :Runit)
)
GOTO :Finish

:Runit
  REM Both TOSCREEN and TOFILE get assigned a trailing space in the FOR loops
  REM above when the FOR loops are evaluating the first item in the list,
  REM "TRUE".  So, the first value of TOSCREEN is "TRUE " (with a trailing
  REM space), the second value is "FALSE" (no trailing or leading space).
  REM Adding the ": =" text after "TOSCREEN" tells the command processor to
  REM remove all spaces from the value in the "TOSCREEN" variable.
  IF "%TOSCREEN: =%"=="TRUE" (
      IF "%TOFILE: =%"=="TRUE" (
          SET TEXT=On screen, and in "FILE.TXT"
          SET TOECHOWHERE="ECHO %%I & ECHO %%I>>FILE.TXT"
        ) ELSE (
          SET TEXT=On screen, not in "FILE.TXT"
          SET TOECHOWHERE="ECHO %%I"
      )
    ) ELSE (
      IF "%TOFILE: =%"=="TRUE" (
          SET TEXT=Not on screen, but in "FILE.TXT"
          SET TOECHOWHERE="ECHO %%I>>FILE.txt"
        ) ELSE (
          SET TEXT=Not on screen, nor in "FILE.TXT"
          SET TOECHOWHERE="ECHO %%I>NUL"
      )
  )
  FOR /F "tokens=*" %%I IN ("%TEXT%") DO %TOECHOWHERE:~1,-1%
GOTO :eof

:Finish
  ECHO Finished [this text to console (screen) only].
  PAUSE
Erstaunlich
quelle
Sie sollten delims=stattdessen verwenden.
scriptmastere02
3
command > file >&1
Otávio Décio
quelle
Es ist schneller, wenn Sie die Daten nicht auf den Bildschirm schreiben, da Sie den Puffer nicht mit Mist füllen, sondern Ihren Batch-Job ausführen lassen. Wenn Sie debuggen, würde ich nicht die> Dateisyntax verwenden.
Zufälliger Entwickler
@andynormancx yup hat vergessen, das einzugeben, anstatt es aus dem CMD auszuschneiden und einzufügen.
Zufälliger Entwickler
Ich konnte die Syntax nicht unter einer Windows-Eingabeaufforderung zum Laufen bringen und habe stattdessen den Befehl type verwendet.
JamesEggers
& 2 funktioniert, aber die Datei wird jetzt nicht erstellt, wenn ich sie teste.
JamesEggers
5
Wenn ich "dir> file.txt> & 2" mache, wird file.txt nicht erstellt. Die Ausgabe des Verzeichnisses wird in der Konsole wiedergegeben, aber die Datei wird nicht erstellt. Die Datei wird erstellt, wenn "> & 2" nicht vorhanden ist.
JamesEggers
2

Wenn Sie die Ausgabedatei anhängen möchten, anstatt sie zu ersetzen, möchten Sie sie möglicherweise verwenden

dir 1>> files.txt 2>> err.txt

oder

dir 1>> files.txt 2>>&1
Jochen
quelle
2

Meine Option war folgende:

Erstellen Sie eine Unterroutine, die die Nachricht aufnimmt und den Prozess des Sendens an die Konsole und die Protokolldatei automatisiert.

setlocal
set logfile=logfile.log

call :screenandlog "%DATE% %TIME% This message goes to the screen and to the log"    

goto :eof

:screenandlog
set message=%~1
echo %message% & echo %message% >> %logfile%
exit /b

Wenn Sie der Nachricht eine Variable hinzufügen, müssen Sie die darin enthaltenen Anführungszeichen entfernen, bevor Sie sie an das Unterprogramm senden. Andernfalls kann Ihr Stapel beschädigt werden. Dies funktioniert natürlich nur zum Echo.

JPZ
quelle
WOW JA! Ich mag das sehr!! Ich habe drei Änderungen vorgenommen, ich hoffe sie gefallen euch. 1) Ich verwende setlocal enabledelayedexpansionstatt nur setlocal 2) Ich verwende die verzögerte Erweiterung für die Variable logfile, also >> !logfile!nicht >> %logfile%innerhalb der Unterroutine. Auf diese Weise funktioniert es, wenn es aus einem Codeblock heraus aufgerufen wird (wie in einer if-Anweisung). 3) Ich habe die Zeile "Nachricht setzen" entfernt, da die zusätzliche Variable nicht benötigt wird. Wir haben es bereits in, $~1also habe ich echo $~1für beide Echo-Befehle.
Nate
2

Ich habe eine einfache C # -Konsole erstellt, die die Echtzeitausgabe sowohl auf dem cmd-Bildschirm als auch im Protokoll verarbeiten kann

class Tee
{
    static int Main(string[] args)
    {
        try
        {
            string logFilePath = Path.GetFullPath(args[0]);

            using (StreamWriter writer = new StreamWriter(logFilePath, true))
            {
                for (int value; (value = Console.In.Read()) != -1;)
                {
                    var word = Char.ConvertFromUtf32(value);
                    Console.Write(word);
                    writer.Write(word);
                }
            }
        }
        catch (Exception)
        {
            return 1;
        }
        return 0;
    }
}

Die Verwendung von Batchdateien entspricht der Verwendung von Unix tee

foo | tee xxx.log

Und hier ist das Repository, das die Tee.exe enthält, falls Sie kein Tool zum Kompilieren von https://github.com/iamshiao/Tee haben

Kreis Hsiao
quelle
1

Ich mag die Antwort von atn, aber es war für mich nicht so trivial, sie herunterzuladen wie wintee , das ebenfalls Open Source ist und nur die Tee-Funktionalität bietet (nützlich, wenn Sie nur Tee und nicht den gesamten Satz von Unix-Dienstprogrammen wollen). Dies erfuhr ich aus der Antwort von davor auf die Ausgabe der Windows-Eingabeaufforderung anzeigen und in eine Datei umleiten , in der Sie auch Verweise auf die Unix-Dienstprogramme finden.

Salbei
quelle
0

Die von "Tomas R" bereitgestellte Lösung funktioniert perfekt für die Frage des OP und ist nativ verfügbar.

Versuchen Sie: chkdsk c:> output.txt | Geben Sie output.txt ein

Die Ausgabe dieses Befehls beinhaltet einen Fertigstellungsprozentsatz, der seriell in die Datei ausgegeben wird, daher sieht sie etwas chaotisch aus (dh der Text wird im Verlauf angehängt). Dies passiert nicht mit den Bits, die an STDOUT (den Bildschirm) ausgegeben werden. So wäre es, wenn Sie denselben Befehl ohne Umleitung ausführen würden.

J0N
quelle
-3

Ich denke, Sie wollen etwas in dieser Richtung:

echo Your Msg> YourTxtFile.txt

Oder wenn Sie eine neue Zeile möchten:

echo Your Msg>> YourTxtFile.txt

Diese Befehle eignen sich hervorragend für Protokolle.

Hinweis: Dies führt manchmal zu Störungen und ersetzt die gesamte Textdatei auf meinem Computer.

Ein weiterer Hinweis: Wenn die Datei nicht vorhanden ist, wird die Datei erstellt.

Gladius125
quelle
1
Nein, OP wollte die Ausgabe in eine Datei und auf dem Bildschirm haben. Ihre schreibt nur in die Datei. (Und >ist entworfen , um die Datei zu überschreiben Verwendung. Anhängen )>>
Stephan