Comment puis-je exécuter une application de ligne de commande dans l'invite de commande Windows et afficher le résultat et le rediriger simultanément vers un fichier?
Si, par exemple, je devais exécuter la commande dir > test.txt
, la sortie serait redirigée vers un fichier nommé test.txt
sans afficher les résultats.
Comment écrire une commande pour afficher la sortie and rediriger la sortie vers un fichier dans l'invite de commande Windows, similaire à la commande tee
de Unix?
Pour développer davor's answer , vous pouvez utiliser PowerShell de la manière suivante:
powershell "dir | tee test.txt"
Si vous essayez de rediriger la sortie d'un fichier exe dans le répertoire en cours, vous devez utiliser .\
sur le nom du fichier, par exemple:
powershell ".\something.exe | tee test.txt"
J'ai été capable de trouver une solution/solution de contournement de la sortie vers un fichier et ensuite vers la console:
dir > a.txt | type a.txt
où dir est la commande dont la sortie doit être redirigée, a.txt un fichier où stocker la sortie.
Il existe un port Win32 de la commande Unix tee
, qui fait exactement cela. Voir http://unxutils.sourceforge.net/ ou http://getgnuwin32.sourceforge.net/
Vérifiez ceci: wintee
Pas besoin de cygwin.
J'ai rencontré et signalé quelques problèmes cependant.
Vous pouvez aussi vérifier nxutils car il contient un tee (et aucun besoin de cygwin), mais sachez que les fichiers EOL en sortie ressemblent à UNIX, comme ici.
Dernier point, mais non le moindre, si vous avez PowerShell, vous pouvez essayer Tee-Object. Tapez get-help tee-object
dans la console PowerShell pour plus d'informations.
@ tori3852
Je l'ai trouvé
dir > a.txt | type a.txt
n'a pas fonctionné (les premières lignes de la liste dir seulement - soupçonnent une sorte de processus et la seconde partie, la commande 'type' s'est terminée avant la fin de la liste?), j'ai donc utilisé:
dir > z.txt && type z.txt
qui a fait - des commandes séquentielles, on complète avant le second commence.
Une simple application console C # ferait l'affaire:
using System;
using System.Collections.Generic;
using System.IO;
namespace CopyToFiles
{
class Program
{
static void Main(string[] args)
{
var buffer = new char[100];
var outputs = new List<TextWriter>();
foreach (var file in args)
outputs.Add(new StreamWriter(file));
outputs.Add(Console.Out);
int bytesRead;
do
{
bytesRead = Console.In.ReadBlock(buffer, 0, buffer.Length);
outputs.ForEach(o => o.Write(buffer, 0, bytesRead));
} while (bytesRead == buffer.Length);
outputs.ForEach(o => o.Close());
}
}
}
Pour utiliser cela, il vous suffit de canaliser la commande source dans le programme et de fournir le chemin de tous les fichiers pour lesquels vous souhaitez dupliquer la sortie. Par exemple:
dir | CopyToFiles files1.txt files2.txt
Affiche les résultats de dir et stocke les résultats dans les fichiers files1.txt et files2.txt.
Notez qu'il n'y a pas beaucoup (quoi que ce soit!) De solutions de traitement des erreurs ci-dessus, et la prise en charge de plusieurs fichiers peut ne pas être réellement nécessaire.
Malheureusement, rien de tel.
Les applications de console Windows ne possèdent qu'un seul descripteur de sortie. (Bien, il y a deux STDOUT
, STDERR
mais cela n'a pas d'importance ici) Le >
redirige la sortie normalement écrite dans le descripteur de console vers un descripteur de fichier.
Si vous souhaitez effectuer un multiplexage, vous devez utiliser une application externe vers laquelle vous pouvez renvoyer la sortie. Cette application peut alors écrire dans un fichier et dans la console à nouveau.
Cela fonctionne, même si c'est un peu moche:
dir >_ && type _ && type _ > a.txt
Elle est un peu plus flexible que certaines des autres solutions, en ce sens qu'elle fonctionne instruction par instruction afin que vous puissiez l'utiliser également pour l'ajouter. J'utilise un peu ces fichiers batch pour enregistrer et afficher des messages:
ECHO Print line to screen and log to file. >_ && type _ && type _ >> logfile.txt
Oui, vous pouvez simplement répéter l’instruction ECHO (une fois pour l’écran et une deuxième fois pour la redirection vers le fichier journal), mais cela semble tout aussi mauvais et représente un problème de maintenance. Au moins, vous ne devrez pas modifier les messages à deux endroits.
Notez que _ n'est qu'un fichier court. Vous devez donc vous assurer de le supprimer à la fin de votre fichier de commandes (si vous utilisez un fichier de commandes).
mété est un petit utilitaire qui fonctionne très bien à cet effet. C'est gratuit, la source est ouverte et ça marche.
Vous pouvez le trouver à http://www.commandline.co.uk .
Utilisée dans un fichier de commandes pour afficher la sortie ET créer un fichier journal simultanément, la syntaxe est la suivante:
someprocess | mtee /+ mylogfile.txt
Où/+ signifie ajouter la sortie.
Cela suppose que vous avez copié mtee dans un dossier qui se trouve dans le PATH, bien sûr.
Je suis d'accord avec Brian Rasmussen, le port unxutils est le moyen le plus simple de procéder. Dans la section Fichiers batch de ses Pages de script , Rob van der Woude fournit une mine d'informations sur l'utilisation des commandes MS-DOS et CMD. Je pensais qu'il aurait peut-être une solution native à votre problème et, après avoir fouillé dans tout cela, j'ai trouvé TEE.BAT , qui semble n'être que cela, une implémentation en langage de traitement par lots de MS-DOS. C'est un fichier batch d'aspect assez complexe et mon penchant serait toujours d'utiliser le portage unxutils.
Si vous avez cygwin dans votre chemin d’environnement Windows, vous pouvez utiliser:
dir > a.txt | tail -f a.txt
Je voudrais développer un peu les propos de Saxon Druce’s excellente réponse .
Comme indiqué, vous pouvez rediriger la sortie d'un exécutable dans le répertoire en cours de la manière suivante:
powershell ".\something.exe | tee test.txt"
Cependant, cela enregistre uniquement stdout
dans test.txt
. Il n’enregistre pas non plus stderr
.
La solution évidente serait d'utiliser quelque chose comme ceci:
powershell ".\something.exe 2>&1 | tee test.txt"
Cependant, cela ne fonctionnera pas pour tous les something.exe
s. Certains something.exe
s interpréteront le 2>&1
comme un argument et échoueront. La bonne solution est d’avoir seulement des apostrophes autour du something.exe
et ses commutateurs et arguments, comme ceci:
powershell ".\something.exe --switch1 --switch2 … arg1 arg2 …" 2>&1 | tee test.txt
dir 1>a.txt 2>&1 | type a.txt
Cela aidera à rediriger STDOUT et STDERR.
Je recherchais également la même solution. Après un peu d’essais, j’ai réussi à atteindre cet objectif dans Invite de commandes. Voici ma solution:
@Echo off
for /f "Delims=" %%a IN (xyz.bat) do (
%%a > _ && type _ && type _ >> log.txt
)
@Echo on
Il capture même toute commande PAUSE.
Quelque chose comme ça devrait faire ce dont vous avez besoin?
%DATE%_%TIME% > c:\a.txt & type c:\a.txt
ipconfig >> c:\a.txt & type c:\a.txt
ping localhost >> c:\a.txt & type c:\a.txt
pause
Voici un exemple de ce que j'ai utilisé à partir d'une autre réponse
@echo off
REM SOME CODE
set __ERROR_LOG=c:\errors.txt
REM set __IPADDRESS=x.x.x.x
REM Test a variable
if not defined __IPADDRESS (
REM Call function with some data and terminate
call :TEE %DATE%,%TIME%,IP ADDRESS IS NOT DEFINED
goto :EOF
)
REM If test happens to be successful, TEE out a message and end script.
call :TEE Script Ended Successful
goto :EOF
REM THE TEE FUNCTION
:TEE
for /f "tokens=*" %%Z in ("%*") do (
> CON ECHO.%%Z
>> "%__ERROR_LOG%" ECHO.%%Z
goto :EOF
)
Je sais que c'est un sujet très ancien, mais dans les réponses précédentes, l'implémentation d'un té en temps réel écrit en batch n'est pas complète. Ma solution ci-dessous est un script hybride Batch-JScript qui utilise la section JScript uniquement pour obtenir le résultat de la commande piped, mais le traitement des données est effectué dans la section Batch. Cette approche présente l’avantage que tout programmeur Batch peut modifier ce programme pour répondre à des besoins spécifiques. Ce programme traite également correctement la sortie de la commande CLS produite par d’autres fichiers Batch, c’est-à-dire qu’il efface l’écran lorsque la sortie de la commande CLS est détectée.
@if (@CodeSection == @Batch) @then
@echo off
setlocal EnableDelayedExpansion
rem APATee.bat: Asynchronous (real time) Tee program, Batch-JScript hybrid version
rem Antonio Perez Ayala
rem The advantage of this program is that the data management is written in Batch code,
rem so any Batch programmer may modify it to fit their own needs.
rem As an example of this feature, CLS command is correctly managed
if "%~1" equ "" (
echo Duplicate the Stdout output of a command in the screen and a disk file
echo/
echo anyCommand ^| APATee teeFile.txt [/A]
echo/
echo If /A switch is given, anyCommand output is *appended* to teeFile.txt
goto :EOF
)
if "%2" equ ":TeeProcess" goto TeeProcess
rem Get the output of CLS command
for /F %%a in ('cls') do set "cls=%%a"
rem If /A switch is not provided, delete the file that receives Tee output
if /I "%~2" neq "/A" if exist %1 del %1
rem Create the semaphore-signal file and start the asynchronous Tee process
echo X > Flag.out
if exist Flag.in del Flag.in
Cscript //nologo //E:JScript "%~F0" | "%~F0" %1 :TeeProcess
del Flag.out
goto :EOF
:TeeProcess
rem Wait for "Data Available" signal
if not exist Flag.in goto TeeProcess
rem Read the line sent by JScript section
set line=
set /P line=
rem Set "Data Read" acknowledgement
ren Flag.in Flag.out
rem Check for the standard "End Of piped File" mark
if "!line!" equ ":_EOF_:" exit /B
rem Correctly manage CLS command
if "!line:~0,1!" equ "!cls!" (
cls
set "line=!line:~1!"
)
rem Duplicate the line in Stdout and the Tee output file
echo(!line!
echo(!line!>> %1
goto TeeProcess
@end
// JScript section
var fso = new ActiveXObject("Scripting.FileSystemObject");
// Process all lines of Stdin
while ( ! WScript.Stdin.AtEndOfStream ) {
// Read the next line from Stdin
var line = WScript.Stdin.ReadLine();
// Wait for "Data Read" acknowledgement
while ( ! fso.FileExists("Flag.out") ) {
WScript.Sleep(10);
}
// Send the line to Batch section
WScript.Stdout.WriteLine(line);
// Set "Data Available" signal
fso.MoveFile("Flag.out", "Flag.in");
}
// Wait for last "Data Read" acknowledgement
while ( ! fso.FileExists("Flag.out") ) {
WScript.Sleep(10);
}
// Send the standard "End Of piped File" mark
WScript.Stdout.WriteLine(":_EOF_:");
fso.MoveFile("Flag.out", "Flag.in");
envoyer la sortie à la console, ajouter au journal de la console, supprimer la sortie de la commande en cours
dir >> usb-create.1 && type usb-create.1 >> usb-create.log | type usb-create.1 && del usb-create.1
@echo on
set startDate=%date%
set startTime=%time%
set /a sth=%startTime:~0,2%
set /a stm=1%startTime:~3,2% - 100
set /a sts=1%startTime:~6,2% - 100
fullprocess.bat > C:\LOGS\%startDate%_%sth%.%stm%.%sts%.LOG | fullprocess.bat
Cela créera un fichier journal avec l’heure actuelle et vous pourrez utiliser les lignes de la console pendant le processus.
Il s’agit d’une variante du précédent answer de MTS, qui ajoute toutefois certaines fonctionnalités pouvant être utiles à d’autres. Voici la méthode que j'ai utilisée:
set _Temp_Msg_Cmd=
.^
afin que les commandes ne soient pas évaluées initialement%~n0_temp.txt
qui utilise syntaxe d'extension de paramètre de ligne de commande%~n0
pour obtenir le nom du fichier de commandes.%~n0_log.txt
Voici la séquence de commandes:
^> %~n0_temp.txt 2^>^&1
^& type %~n0_temp.txt ^>^> %~n0_log.txt
^& type %~n0_temp.txt
^& del /Q /F %~n0_temp.txt
Voici l'exemple:
set _Temp_Msg_Cmd= ^> %~n0_temp.txt 2^>^&1 ^& type %~n0_temp.txt ^>^> %~n0_log.txt ^& type %~n0_temp.txt ^& del /Q /F %~n0_temp.txt
De cette façon, la commande peut simplement être ajoutée après les commandes ultérieures dans un fichier de commandes qui semble beaucoup plus propre:
echo test message %_Temp_Msg_Cmd%
Cela peut également être ajouté à la fin des autres commandes. Autant que je sache, cela fonctionnera lorsque les messages ont plusieurs lignes. Par exemple, la commande suivante génère deux lignes en cas de message d'erreur:
Net Use M: /D /Y %_Temp_Msg_Cmd%
Juste comme Unix.
dir | tee a.txt
Cela fonctionne-t-il sur Windows XP, il faut que mksnt
soit installé.
Il s’affiche sur l’invite et s’ajoute au fichier.
Si vous êtes sur la CLI, pourquoi ne pas utiliser une boucle FOR pour "FAIRE" ce que vous voulez:
for /F "delims=" %a in ('dir') do @echo %a && echo %a >> output.txt
Excellente ressource sur Windows CMD pour les boucles: https://ss64.com/nt/for_cmd.html La clé ici consiste à définir les délimètres (delims), qui rompraient chaque ligne de sortie, en rien . De cette façon, il ne sera pas cassé sur le défaut d'espace blanc. Le% a est une lettre arbitraire, mais il est utilisé dans la section "faire" pour, eh bien ... faire quelque chose avec les caractères qui ont été analysés à chaque ligne. Dans ce cas, vous pouvez utiliser les esperluettes (&&) pour exécuter la commande 2nd echo afin de créer ou d'ajouter (>>) à un fichier de votre choix. Il est plus sûr de conserver cet ordre de commandes DO au cas où il y aurait un problème lors de l'écriture du fichier. Au moins, nous enverrons d'abord l'écho à la console. Le signe at (@) en face du premier écho empêche la console d'afficher la commande echo elle-même et affiche simplement le résultat de la commande qui consiste à afficher les caractères dans% a. Sinon, vous verriez:
echo Volume dans le lecteur [x] est Windows
Le volume dans le lecteur [x] correspond à Windows.
UPDATE:/F ignore les lignes vierges et seul correctif consiste à pré-filtrer la sortie en ajoutant un caractère à chaque ligne (éventuellement avec des numéros de ligne via la commande find). La résolution de ce problème dans l'interface de ligne de commande n'est ni rapide ni jolie. De plus, je n’ai pas inclus STDERR, alors voici des erreurs de capture:
for /F "delims=" %a in ('dir 2^>^&1') do @echo %a & echo %a >> output.txt
redirection des messages d'erreur
Les carets (^) sont là pour échapper aux symboles qui les suivent, car la commande est une chaîne interprétée, par opposition à une saisie directe sur la ligne de commande.
J'utilise un sous-programme batch avec une instruction "for" pour obtenir la sortie de la commande ligne par ligne et les deux écrivent cette ligne dans un fichier et la renvoient sur la console.
@echo off
set logfile=test.log
call :ExecuteAndTee dir C:\Program Files
Exit /B 0
:ExecuteAndTee
setlocal enabledelayedexpansion
echo Executing '%*'
for /f "delims=" %%a in ('%* 2^>^&1') do (echo.%%a & echo.%%a>>%logfile%)
endlocal
Exit /B 0
Une alternative consiste à choisir stdout to stderr dans votre programme:
en Java:
System.setOut(new PrintStream(new TeeOutputStream(System.out, System.err)));
Ensuite, dans votre fichier batch DOS: Java program > log.txt
La stdout ira au fichier journal et la stderr (mêmes données) s'affichera sur la console.
Une autre variante consiste à scinder le tuyau, puis à rediriger la sortie comme vous le souhaitez.
@echo off
for /f "tokens=1,* delims=:" %%P in ('findstr /n "^"') do (
echo.%%Q
echo.%%Q>&3
)
@exit/b %errorlevel%
Enregistrez ce qui précède dans un fichier .bat. Il divise également la sortie texte de filestream 1 en filestream 3, que vous pouvez rediriger au besoin. Dans mes exemples ci-dessous, j'ai appelé le script ci-dessus splitPipe.bat ...
dir | splitPipe.bat 1>con 2>&1 3>my_stdout.log
splitPipe.bat 2>nul < somefile.txt
J'installe Perl sur la plupart de mes machines, donc une réponse à l'aide de Perl: tee.pl
my $file = shift || "tee.dat";
open $output, ">", $file or die "unable to open $file as output: $!";
while(<STDIN>)
{
print $_;
print $output $_;
}
close $output;
dir | Perl tee.pl ou dir | Perl tee.pl dir.bat
brut et non testé.
Cela fonctionne en temps réel mais est aussi un peu moche et la performance est lente. Pas bien testé non plus:
@echo off
cls
SET MYCOMMAND=dir /B
ECHO File called 'test.bat' > out.txt
for /f "usebackq delims=" %%I in (`%MYCOMMAND%`) do (
ECHO %%I
ECHO %%I >> out.txt
)
pause
Comment puis-je afficher et rediriger la sortie vers un fichier. Supposons que si j'utilise la commande dos, dir> test.txt, cette commande redirige la sortie vers le fichier test.txt sans afficher les résultats. comment écrire une commande pour afficher la sortie et rediriger la sortie vers un fichier à l'aide de DOS, c'est-à-dire l'invite de commande Windows, pas sous UNIX/LINUX.
Vous pouvez trouver ces commandes en biterscripting ( http://www.biterscripting.com ) utiles.
var str output
lf > $output
echo $output # Will show output on screen.
echo $output > "test.txt" # Will write output to file test.txt.
system start "test.txt" # Will open file test.txt for viewing/editing.
Suivre aide si vous voulez quelque chose de vraiment vu à l’écran - même si le fichier de commandes a été redirigé vers un fichier. Le périphérique CON peut également être utilisé s'il est redirigé vers un fichier
Exemple:
ECHO first line on normal stdout. maybe redirected
ECHO second line on normal stdout again. maybe redirected
ECHO third line is to ask the user. not redirected >CON
ECHO fourth line on normal stdout again. maybe redirected
Voir aussi la bonne description de la redirection: http://www.p-dd.com/chapter7-page14.html