windows - Hvordan ekko og send konsoludgang til en fil i et flagermusskript?

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg har et batch script, der udfører en opgave og sender output til en tekstfil. Er der også mulighed for at få outputvisning på konsolvinduet?


For eksempel:


c:Windows>dir > windows-dir.txt


Er der mulighed for at få udgangen af ​​dir displayet i konsolvinduet og sætte det i tekstfilen?

Bedste reference


Redigeret bit >> tldr; Nej, det kan du ikke.


Jeg forsøger at forklare omdirigeringen lidt.


Du omdirigerer en af ​​de ti strømme med > fil eller < fil

Det er ubetydeligt, hvis omdirigering er før eller efter kommandoen,
så disse to linjer er næsten ens.


dir > file.txt
> file.txt dir


Omdirigering i dette eksempel er kun en genvej til 1> , det vil sige stream 1 (STDOUT) bliver omdirigeret.

Så du kan omdirigere enhver strøm ved at udpege nummeret som 2> err.txt , og det er også tilladt at omdirigere flere streams i en linje.


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


I dette eksempel vil 'standard output' gå ind i files.txt, alle fejl vil være i err.txt og stream3 vil gå ind i nothing.txt (DIR bruger ikke stream 3).

Stream0 er STDIN

Stream1 er STDOUT

Stream2 er STDERR

Stream3-9 bruges ikke



Men hvad sker der, hvis du forsøger at omdirigere den samme stream flere gange?


dir > files.txt > two.txt


'Der kan kun være en', og det er altid den sidste!

Så det er lig med dir> two.txt


Ok, der er en ekstra mulighed, der omdirigerer en strøm til en anden strøm.


dir 1>files.txt 2>&1 


2> &1 omdirigeringer stream2 til stream1 og 1> files.txt omdirigerer alle til files.txt .

Ordren er vigtig her!


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


er forskellige. Den første omdirigerer alle (STDOUT og STDERR) til NUL,

men den anden linje omdirigerer STDOUT til NUL og STDERR til den 'tomme' STDOUT.


Som en konklusion er det indlysende, hvorfor eksemplerne på Otávio Décio og andynormancx ikke kan fungere.


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


Begge forsøger at omdirigere stream1 to gange, men 'Der kan kun være en', og det er altid den sidste.

Så får du


command 1>&1
dir 1>&2


Og i den første prøve omdirigering af stream1 til stream1 er ikke tilladt (og ikke særlig nyttig).


Håber det hjælper.

Andre referencer 1


Brug blot Windows-versionen af ​​UNIX-tee-kommandoen (fundet fra http://unxutils.sourceforge.net) på denne måde: [30]


mycommand > tee outpu\_file.txt


Hvis du også har brug for STDERR-udgangen, skal du bruge følgende.

2>&1 kombinerer STDERR-udgangen til STDOUT (den primære stream).


mycommand 2>&1 | tee output\_file.txt

Andre referencer 2


Hvis du ikke har brug for output i realtid (det vil sige som programmet skriver det) kan du tilføje


type windows-dir.txt


efter den linje.

Andre referencer 3


Den løsning, der fungerede for mig var: dir> a.txt | skriv a.txt.

Andre referencer 4


Ja, der er en måde at vise en enkelt kommando output på konsollen (skærm) og i en fil. Brug dit eksempel, brug ...


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


Detaljeret forklaring:


Kommandoen FOR analyserer udgangen af ​​en kommando eller tekst i en variabel, som kan refereres flere gange.


For en kommando, som f.eks. DIR /B, vedlægges i enkelt citater som vist i eksempel nedenfor. Udskift teksten DIR /B med den ønskede kommando.


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


For at vise tekst, vedhæft tekst i dobbelt citater som vist i eksempel nedenfor.


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


... Og med indpakning af linjer ...


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


Hvis du har tidspunkter, hvor du kun vil have output på konsollen (skærm) og andre gange kun sendt til filen og andre gange sendt til begge, skal du angive 'DO' -klausulen i FOR-sløjfen ved hjælp af en variabel som vist nedenfor med [[\%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

Andre referencer 5


command > file >&1

Andre referencer 6


Hvis du vil tilføje i stedet for at erstatte outputfilen, kan du bruge den


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


eller


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

Andre referencer 7


Jeg kan godt lide atn 's svar, men det var ikke så trivielt for mig at downloade som wintee, som også er open source og kun giver tee funktionaliteten (nyttig hvis du bare vil have tee og ikke hele sæt af Unix utilities). Jeg lærte om dette fra davares svar til Viser Windows kommandoprompt output og omdirigere den til en fil, hvor du også finder reference til Unix-værktøjerne. [32]

Andre referencer 8


Min mulighed var dette:


Opret en underrutine, der tager meddelelsen og automatiserer processen med at sende den til både konsol og logfil.


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


Hvis du tilføjer en variabel til meddelelsen, skal du fjerne citaterne i den, inden du sender den til underrutinen, eller den kan skrue din batch.
Selvfølgelig virker dette kun for ekko.

Andre referencer 9


Jeg lavede en simpel C # -konsol, der kan håndtere realtidsudgang til både cmd-skærmen og loggen


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;
    }
}


Batchfilanvendelsen er den samme som for, hvordan du bruger Unix tee


foo | tee xxx.log


Og her er depotet, der indeholder Tee.exe, hvis du ikke har værktøj til at kompilere
https://github.com/iamshiao/Tee[34]

Andre referencer 10


Løsningen leveret af 'Tomas R' fungerer perfekt til OP 's spørgsmål og det er internt tilgængeligt.


Prøve:
chkdsk c:> output.txt | skriv output.txt


Udgangen er af denne kommando indebærer en færdiggørelsesprocent, der får serielt output til filen, og derfor vil det se lidt rodet ud (dvs. teksten vil blive tilføjet som den fremskridt). Dette sker ikke med de bits, der får output til STDOUT (skærmen). Det er, hvordan det ville være, hvis du bare gør den samme kommando uden omdirigering.