Comment envoyer un écho et envoyer la sortie de la console à un fichier dans un script bat?

136

J'ai un script batch qui exécute une tâche et envoie la sortie dans un fichier texte. Existe-t-il également un moyen d'afficher la sortie sur la fenêtre de la console?

Par exemple:

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

Existe-t-il un moyen d' dirafficher la sortie de l' affichage dans la fenêtre de la console et de la placer dans le fichier texte?

JamesEggers
la source
Voici les redirections que vous pouvez faire, et quelques exemples. <br> J'espère que ça aide :)
emoSTN
Veuillez noter, @Vadzim, qu'une question posée le 2 février 2009 à 16h38 ne peut être considérée comme un double d'une question posée près de trois mois plus tard le 28 avril 2009 à 06h32.
Compo du

Réponses:

216

Non, vous ne pouvez pas avec la redirection pure.
Mais avec quelques astuces (comme tee.bat ) vous pouvez.

J'essaye d'expliquer un peu la redirection.

Vous redirigez l'un des dix flux avec > fichier ou <fichier.
Cela n'a pas d'importance, si la redirection est avant ou après la commande, donc ces deux lignes sont presque les mêmes.

dir > file.txt
> file.txt dir

La redirection dans cet exemple n'est qu'un raccourci pour 1> , cela signifie que le flux 1 (STDOUT) sera redirigé.
Ainsi, vous pouvez rediriger n'importe quel flux en ajoutant le numéro comme 2> err.txt et il est également permis de rediriger plusieurs flux sur une seule ligne.

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

Dans cet exemple, la "sortie standard" ira dans files.txt, toutes les erreurs seront dans err.txt et le stream3 ira dans rien.txt (DIR n'utilise pas le stream 3).
Stream0 est STDIN
Stream1 est STDOUT
Stream2 est STDERR
Stream3-9 n'est pas utilisé

Mais que se passe-t-il si vous essayez de rediriger le même flux plusieurs fois?

dir > files.txt > two.txt

"Il ne peut y en avoir qu'un", et c'est toujours le dernier!
Donc, il est égal à dir> two.txt

Ok, il y a une possibilité supplémentaire, rediriger un flux vers un autre flux.

dir 1>files.txt 2>&1 

2> & 1 redirige stream2 vers stream1 et 1> files.txt redirige tout vers files.txt .
L'ordre est important ici!

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

sont différents. Le premier redirige tout (STDOUT et STDERR) vers NUL,
mais la seconde ligne redirige le STDOUT vers NUL et STDERR vers le STDOUT "vide".

En guise de conclusion, il est évident que les exemples d'Otávio Décio et d'andynormancx ne peuvent pas fonctionner.

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

Les deux essaient de rediriger stream1 deux fois, mais "Il ne peut y en avoir qu'un", et c'est toujours le dernier.
Alors vous obtenez

command 1>&1
dir 1>&2

Et dans le premier exemple, la redirection de stream1 vers stream1 n'est pas autorisée (et pas très utile).

J'espère que ça aide.

jeb
la source
24
C'est donc impossible avec le shell Windows natif
Fantastory
7
@fantastory C'est possible, voir cette excellente solution de dbenham Windows batch: commande 'tee'
jeb
97
Je ne peux pas croire que je viens de lire cet article en entier pour découvrir que tout cela peut être résumé comme "Non".
Charles McKelvey
1
Qu'en est-il du deuxième mécanisme "gérer la duplication"? J'ai expérimenté avec 3<&2(notez le LT au lieu de GT), puis 3>errors.txt. Mais cela s'est mal terminé - toutes les sorties stderr suivantes ont été capturées errors.txt(c'est-à-dire aussi à partir d'autres commandes!).
Tomasz Gandor
Vous pouvez utiliser for /f "delims=" %%v in ('dir') do echo %%v>>file.txtcependant.
scriptmastere02
32

Utilisez simplement la version Windows de la commande UNIX tee (disponible sur http://unxutils.sourceforge.net ) de cette manière:

mycommand > tee outpu_file.txt

Si vous avez également besoin de la sortie STDERR, utilisez ce qui suit.
Le 2>&1combine la sortie STDERR en STDOUT (le flux principal).

mycommand 2>&1 | tee output_file.txt
atn
la source
3
Le Tee-Object PowerShell offre des fonctionnalités similaires. Get-Process | Tee-Object -file c: \ scripts \ test.txt
Kevin Obee
J'ai essayé cela à la fois dans PowerShell et dans le shell régulier. 1>tee a.txtredirigera stdout vers un fichier nommé teeau lieu d'appeler la teecommande. Quelqu'un peut-il confirmer que cette réponse fonctionne pour eux?
mafu du
@mafu je peux le confirmer.
Cerno
@mafu La réponse ci-dessus est légèrement incohérente. Vous devez utiliser le tube "|" au lieu du ">" dans l'exemple du haut. Bizarrement, l'ordre des sorties STDOUT et STDERR était mélangé sur la ligne de commande dans ce cas. L'exemple du bas fonctionne parfaitement pour moi cependant.
Cerno
De plus, le téléchargement de sourceforge a été interrompu pour moi. J'ai trouvé un hôte alternatif ici: wzw.tum.de/public-html/syring/win32/UnxUtilsDist.html (Université de Munich)
Cerno
9

Si vous n'avez pas besoin de la sortie en temps réel (c'est-à-dire pendant que le programme l'écrit), vous pouvez ajouter

type windows-dir.txt

après cette ligne.

Mark Pim
la source
ou sur la même ligne (utile à l'invite): dir > windows-dir.txt & type windows-dir.txt. Cela vaut également pour les blocs: ( echo %date% <NL> echo %username% <NL> echo %time% <NL> pause>CON )>test.txt & type test.txt. Cependant, si la sortie est requise en temps réel, vous pouvez utiliser par exemple un port windows de l' outil tee pour cela…
mousio
7

La solution qui a fonctionné pour moi était: dir> a.txt | tapez a.txt .

NSPKUWCExi2pr8wVoGNk
la source
2
Cela fonctionne avec une commande à faible rendement. Avec une commande de sortie volumineuse, cela ne fonctionne pas car il n'affiche que le premier tampon. Il demande une sortie en temps réel tout en enregistrant la sortie dans un fichier journal.
NetVicious
Ce serait problématique si vous utilisez >> au lieu de>
Nime Cloud
6

Oui, il existe un moyen d'afficher une seule sortie de commande sur la console (écran) et dans un fichier. En utilisant votre exemple, utilisez ...

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

Explication détaillée:

La FORcommande analyse la sortie d'une commande ou d'un texte dans une variable, qui peut être référencée plusieurs fois.

Pour une commande, telle que DIR /B, mettez entre guillemets simples comme indiqué dans l'exemple ci-dessous. Remplacez le DIR /Btexte par la commande souhaitée.

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

Pour afficher du texte, placez le texte entre guillemets, comme indiqué dans l'exemple ci-dessous.

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

... et avec un habillage de ligne ...

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

Si vous avez des moments où vous souhaitez que la sortie soit uniquement sur la console (écran), et d'autres fois envoyés uniquement au fichier, et d'autres fois envoyés aux deux, spécifiez la clause "DO" de la boucle FOR à l'aide d'une variable, comme indiqué ci-dessous avec %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
Amazinate
la source
Vous devriez utiliser à la delims=place.
scriptmastere02
3
command > file >&1
Otávio Décio
la source
C'est plus rapide lorsque vous n'écrivez pas les données à l'écran car vous ne remplissez pas le tampon avec de la merde, mais vous laissez plutôt le travail par lots. si vous déboguez, je n'utiliserais pas la syntaxe de fichier>.
Développeur aléatoire le
@andynormancx yup a oublié de taper cela au lieu de couper-coller à partir du CMD.
Développeur aléatoire le
Je n'ai pas pu faire fonctionner la syntaxe sous une invite de commande Windows et j'ai choisi la commande type à la place.
JamesEggers
& 2 fonctionne mais le fichier n'est pas en cours de création lorsque je le teste.
JamesEggers
5
si je fais "dir> file.txt> & 2" file.txt n'est pas créé. La sortie du répertoire est renvoyée dans la console mais le fichier n'est pas en cours de création. Le fichier est créé lorsque le "> & 2" n'est pas présent.
JamesEggers
2

Si vous souhaitez ajouter au lieu de remplacer le fichier de sortie, vous pouvez utiliser

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

ou

dir 1>> files.txt 2>>&1
Jochen
la source
2

Mon option était la suivante:

Créez un sous-programme qui prend le message et automatise le processus d'envoi à la fois à la console et au fichier journal.

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

Si vous ajoutez une variable au message, assurez-vous de supprimer les guillemets avant de l'envoyer au sous-programme ou il peut visser votre lot. Bien sûr, cela ne fonctionne que pour l'écho.

JPZ
la source
WOW OUI! J'aime vraiment ça !! J'ai cependant fait trois changements, j'espère qu'ils vous plairont. 1) J'utilise setlocal enabledelayedexpansionau lieu de juste setlocal 2) J'utilise l'expansion retardée pour la variable de fichier journal, donc >> !logfile!au lieu de >> %logfile%dans le sous-programme. De cette façon, il fonctionne lorsqu'il est appelé depuis un bloc de code (comme dans une instruction if). 3) J'ai supprimé la ligne "set message" car il n'y a pas besoin de la variable supplémentaire. Nous l'avons déjà dans $~1donc je l'ai echo $~1pour les deux commandes d'écho.
Nate le
2

J'ai créé une console C # simple qui peut gérer la sortie en temps réel à la fois sur l'écran cmd et le journal

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

L'utilisation du fichier batch est la même que la façon dont vous utilisez Unix tee

foo | tee xxx.log

Et voici le référentiel qui inclut le Tee.exe au cas où vous n'auriez pas d'outil pour compiler https://github.com/iamshiao/Tee

Cercle Hsiao
la source
1

J'aime la réponse d'ATN, mais ce n'était pas aussi simple pour moi de télécharger que wintee , qui est également open source et ne donne que la fonctionnalité tee (utile si vous voulez juste un tee et pas l'ensemble des utilitaires unix). J'ai appris cela grâce à la réponse de davor à Afficher la sortie de l'invite de commande Windows et à la rediriger vers un fichier , où vous trouverez également des références aux utilitaires unix.

sauge
la source
0

La solution fournie par "Tomas R" fonctionne parfaitement pour la question de l'OP et est disponible nativement.

Essayez: chkdsk c:> output.txt | tapez output.txt

La sortie est de cette commande implique un pourcentage d'achèvement qui obtient une sortie en série dans le fichier, par conséquent, il semblera un peu désordonné (c'est-à-dire que le texte sera ajouté au fur et à mesure de sa progression). Cela n'arrive pas aux bits qui sont envoyés à STDOUT (l'écran). C'est ainsi que ce serait si vous exécutiez simplement la même commande sans redirection.

J0N
la source
-3

Je pense que vous voulez quelque chose du genre:

echo Your Msg> YourTxtFile.txt

Ou si vous voulez une nouvelle ligne:

echo Your Msg>> YourTxtFile.txt

Ces commandes sont parfaites pour les journaux.

Remarque: Cela va parfois pépin et remplacer tout le fichier texte sur mon ordinateur.

Autre note: si le fichier n'existe pas, il créera le fichier.

Gladius125
la source
1
non, OP voulait avoir la sortie dans un fichier et à l'écran. Le vôtre écrit simplement dans le fichier. (Et >est conçu pour écraser le fichier. Utilisez >>pour ajouter )
Stephan