Windowsのコマンドプロンプトでコマンドラインアプリケーションを実行し、同時に出力を表示してファイルにリダイレクトするにはどうすればよいですか。
たとえば、コマンドdir > test.txt
を実行すると、結果が表示されずに出力がtest.txt
というファイルにリダイレクトされます。
UNIXのtee
コマンドのように、Windowsコマンドプロンプトで出力を表示するコマンドとを出力にリダイレクトするコマンドを書くにはどうすればよいですか。
davorの答え を拡張するには、次のようにPowerShellを使用します。
powershell "dir | tee test.txt"
現在のディレクトリにあるexeの出力をリダイレクトしようとしているのなら、ファイル名に.\
を使う必要があります。例えば:
powershell ".\something.exe | tee test.txt"
出力をファイルにリダイレクトしてからコンソールにリダイレクトするという解決策/回避策を見つけることができました。
dir > a.txt | type a.txt
ここで、dirは、出力をリダイレクトする必要があるコマンドです。a.txt出力を保存するファイル.
Win32のUnixのtee
コマンドがあります。 http://unxutils.sourceforge.net/ または http://getgnuwin32.sourceforge.net/ を参照してください。
@ tori3852
見つけた
dir > a.txt | type a.txt
うまくいきませんでした(最初の数行のdirリストのみ - ある種のプロセスフォークと2番目の部分、 'type'コマンドがdireリストが完了する前に終了したのではないか?)
dir > z.txt && type z.txt
それがした - シーケンシャルコマンド、2番目が始まる前に1つのコマンド。
簡単なC#コンソールアプリケーションでうまくいくでしょう。
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());
}
}
}
これを使用するには、sourceコマンドをプログラムにパイプして、出力を複製したいファイルのパスを指定するだけです。例えば:
dir | CopyToFiles files1.txt files2.txt
Dirの結果を表示するとともに、結果をfiles1.txtとfiles2.txtの両方に保存します。
上記のエラー処理の方法はそれほど多くありません。複数のファイルをサポートすることは実際には必要ないかもしれません。
残念ながら、そのようなことはありません。
Windowsコンソールアプリケーションには、単一の出力ハンドルしかありません。 (STDOUT
、STDERR
が2つありますが、ここでは関係ありません)>
は、通常コンソールハンドルに書き込まれる出力をファイルハンドルにリダイレクトします。
ある種の多重化をしたい場合は、出力を転送できる外部アプリケーションを使用する必要があります。このアプリケーションはファイルとコンソールに再度書き込むことができます。
ちょっと醜いですがこれはうまくいきます:
dir >_ && type _ && type _ > a.txt
他のいくつかのソリューションよりも少し柔軟性があります。ステートメントごとに機能するので、追加して使用することもできます。私はメッセージをログに記録して表示するためにバッチファイルでかなりこれを使います:
ECHO Print line to screen and log to file. >_ && type _ && type _ >> logfile.txt
はい、ECHOステートメントを繰り返すことができます(画面用に1回とログファイルへの2回目のリダイレクト)。ただし、これはまったく同じように見え、メンテナンス上の問題です。少なくともこの方法では、2箇所でメッセージを変更する必要はありません。
_は単なる短いファイル名なので、バッチファイルの最後で必ず削除する必要があります(バッチファイルを使用している場合)。
mteeはこの目的のために非常にうまく機能する小さなユーティリティです。それは無料で、ソースはオープンです、そしてそれはJust Worksです。
あなたはそれを見つけることができます http://www.commandline.co.uk 。
出力を表示し、同時にログファイルを作成するためにバッチファイルで使用される構文は次のようになります。
someprocess | mtee /+ mylogfile.txt
/ +は出力を追加することを意味します。
これは、あなたがmteeをPATHにあるフォルダにコピーしたことを前提としています。
私はBrian Rasmussenに同意します、unxutilsポートはこれをする最も簡単な方法です。 Batch Files /彼の スクリプトページ Rob van der Woudeには、MSの使用に関する豊富な情報が記載されています。 -DOSおよびCMDコマンド私は彼があなたの問題に対するネイティブな解決策を持っているのではないかと考え、そこを掘り下げた後、私は TEE.BAT を見つけました。ティーの。それはかなり複雑に見えるバッチファイルです、そして私の傾向はまだunxutilsポートを使うことでしょう。
あなたのウィンドウズ環境パスにcygwinがあるなら、あなたは使うことができます:
dir > a.txt | tail -f a.txt
Saxon Druceの 優れた回答 について少し詳しく説明します。
すでに述べたように、現在のディレクトリにある実行可能ファイルの出力を次のようにリダイレクトできます。
powershell ".\something.exe | tee test.txt"
ただし、これはstdout
をtest.txt
に記録するだけです。 stderr
も記録されません。
明白な解決策はこのようなものを使うことでしょう:
powershell ".\something.exe 2>&1 | tee test.txt"
ただし、これはすべてのsomething.exe
sには効果がありません。 something.exe
の中には2>&1
を引数として解釈して失敗するものがあります。正しい解決策は、代わりにsomething.exe
とそのスイッチと引数をアポストロフィで囲むことです。
powershell ".\something.exe --switch1 --switch2 … arg1 arg2 …" 2>&1 | tee test.txt
dir 1>a.txt 2>&1 | type a.txt
これはSTDOUTとSTDERRの両方をリダイレクトするのに役立ちます。
私も同じ解決策を探していました、少し試した後、私はコマンドプロンプトでそれを達成することに成功しました。これが私の解決策です:
@Echo off
for /f "Delims=" %%a IN (xyz.bat) do (
%%a > _ && type _ && type _ >> log.txt
)
@Echo on
それはどんなPAUSEコマンドでも捕らえます。
コンソールへの出力の送信、コンソールログへの追加、現在のコマンドからの出力の削除
dir >> usb-create.1 && type usb-create.1 >> usb-create.log | type usb-create.1 && del usb-create.1
このような何かはあなたが必要なことをするべきですか?
%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
これは私が他の答えの1つに基づいて使用したもののサンプルです。
@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
)
これは非常に古いトピックですが、以前の回答では、バッチで書かれたリアルタイムのティーの完全な実装はありません。以下の私の解決策は、パイプ処理されたコマンドからの出力を取得するためだけにJScriptセクションを使用するBatch-JScriptハイブリッドスクリプトですが、データの処理はBatchセクションで行われます。このアプローチには、特定のニーズに合わせてすべてのBatchプログラマーがこのプログラムを変更できるという利点があります。このプログラムは、他のバッチファイルによって生成されたCLSコマンドの出力も正しく処理します。つまり、CLSコマンドの出力が検出されると画面をクリアします。
@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");
@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
これにより、現在の日時を含むログファイルが作成され、プロセス中にコンソール行を表示できます。
これは以前のMTSによる answer のバリエーションですが、他の人にとって役立つかもしれない機能をいくつか追加しています。私が使用した方法は次のとおりです。
set _Temp_Msg_Cmd=
を使用してコマンドウィンドウに出力し、ログファイルに追加できます。^
文字を使用して、コマンドが最初に評価されないようにしました%~n0_temp.txt
と呼ばれる実行中のバッチファイルに似たファイル名で一時ファイルが作成されます。このファイルは、 コマンドラインパラメーター拡張構文%~n0
を使用してバッチファイルの名前を取得します。%~n0_log.txt
に追加されますコマンドのシーケンスは次のとおりです。
^> %~n0_temp.txt 2^>^&1
に送信されます^& type %~n0_temp.txt ^>^> %~n0_log.txt
^& type %~n0_temp.txt
^& del /Q /F %~n0_temp.txt
以下に例を示します。
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
このようにすれば、バッチファイル内のコマンドが後のコマンドの後に追加されるだけで、よりきれいになります。
echo test message %_Temp_Msg_Cmd%
これは、他のコマンドの最後にも追加できます。私が知る限り、メッセージに複数の行が含まれている場合に機能します。たとえば、次のコマンドは、エラーメッセージがある場合に2行を出力します。
Net Use M: /D /Y %_Temp_Msg_Cmd%
CLIを使用している場合は、FORループを使用して必要なものを "DO"しないでください。
for /F "delims=" %a in ('dir') do @echo %a && echo %a >> output.txt
ループのためのWindows CMDの素晴らしいリソース: https://ss64.com/nt/for_cmd.html ここで重要なのは、区切り文字(delims)を設定することです。これは、出力の各行を何もしない、に分割します。このようにして、デフォルトの空白文字では壊れません。 %aは任意の文字ですが、 "do"セクションで、各行で解析された文字を使って何かをするために使用されています。この場合、アンパサンド(&&)を使用して2番目のechoコマンドを実行し、選択したファイルにcreate-or-append(>>)します。ファイルの書き込みに問題がある場合に備えて、このDOコマンドの順序を守ったほうが安全です。少なくとも最初にコンソールにエコーが表示されます。最初のエコーの前にあるアットマーク(@)は、コンソールがechoコマンド自体を表示するのを抑制し、代わりに%aで文字を表示することになっているコマンドの結果を表示するだけです。そうでなければあなたが見るでしょう:
エコードライブ[x]のボリュームはWindowsです。
ドライブ[x]のボリュームはWindowsです
更新:/ Fは空白行をスキップし、唯一の修正はすべての行に文字を追加する出力を事前にフィルタリングすることです(多分コマンドfindを介して行番号で)。 CLIでこれを解決するのは速くも美しくもありません。また、私はSTDERRを含めなかったので、ここでも同様にエラーをとらえています:
for /F "delims=" %a in ('dir 2^>^&1') do @echo %a & echo %a >> output.txt
コマンドは、コマンドラインで直接入力するのではなく、解釈される文字列であるため、キャレット(^)はそれらの後のシンボルをエスケープするためにあります。
"for"ステートメントを含むバッチサブルーチンを使用して、一度に1行ずつコマンド出力を取得し、両方ともその行をファイルに書き込み、それをコンソールに出力します。
@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
別の方法としては、プログラム内で標準出力を標準エラー出力に変換します。
javaでは:
System.setOut(new PrintStream(new TeeOutputStream(System.out, System.err)));
次に、dosバッチファイルで、Java program > log.txt
を入力します。
標準出力はログファイルに出力され、標準エラー出力(同じデータ)がコンソールに表示されます。
もう1つのバリエーションは、パイプを分割してから好きなように出力をリダイレクトすることです。
@echo off
for /f "tokens=1,* delims=:" %%P in ('findstr /n "^"') do (
echo.%%Q
echo.%%Q>&3
)
@exit/b %errorlevel%
上記を.batファイルに保存します。ファイルストリーム1のテキスト出力もファイルストリーム3に分割され、必要に応じてリダイレクトできます。以下の例では、上記のスクリプトsplitPipe.batを呼び出しました。
dir | splitPipe.bat 1>con 2>&1 3>my_stdout.log
splitPipe.bat 2>nul < somefile.txt
私はほとんどのマシンにPerlをインストールしているので、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またはdir | Perl tee.pl dir.bat
原油と未試験。
UNIXと同じです。
dir | tee a.txt
Windows XPでは動作しますが、mksnt
をインストールする必要があります。
ファイルに追加するだけでなく、プロンプトにも表示されます。
これはリアルタイムで動作しますが、やや醜いパフォーマンスも遅くなります。十分にテストされていません。
@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
出力を表示してファイルにリダイレクトする方法dosコマンド、dir> test.txtを使用すると、このコマンドは結果を表示せずに出力をファイルtest.txtにリダイレクトします。 UNIX/LINUXではなく、DOSを使用して出力を表示し、出力をファイルにリダイレクトするためのコマンドの書き方。
これらのコマンドはbiterscripting( http://www.biterscripting.com )に役立ちます。
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.
バッチファイルがファイルにリダイレクトされている場合でも、画面上に実際に表示されるものが必要な場合は、以下の手順に従ってください。デバイスCONは、ファイルにリダイレクトされている場合にも使用できます。
例:
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
また、適切なリダイレクトの説明を参照してください。 http://www.p-dd.com/chapter7-page14.html