web-dev-qa-db-ja.com

Windowsコマンドプロンプト出力の表示とファイルへのリダイレクト

Windowsのコマンドプロンプトでコマンドラインアプリケーションを実行し、同時に出力を表示してファイルにリダイレクトするにはどうすればよいですか。

たとえば、コマンドdir > test.txtを実行すると、結果が表示されずに出力がtest.txtというファイルにリダイレクトされます。

UNIXのteeコマンドのように、Windowsコマンドプロンプトで出力を表示するコマンドを出力にリダイレクトするコマンドを書くにはどうすればよいですか。

334
Ammu

davorの答え を拡張するには、次のようにPowerShellを使用します。

powershell "dir | tee test.txt"

現在のディレクトリにあるexeの出力をリダイレクトしようとしているのなら、ファイル名に.\を使う必要があります。例えば:

powershell ".\something.exe | tee test.txt"
126
Saxon Druce

出力をファイルにリダイレクトしてからコンソールにリダイレクトするという解決策/回避策を見つけることができました。

dir > a.txt | type a.txt

ここで、dirは、出力をリダイレクトする必要があるコマンドです。a.txt出力を保存するファイル.

124

Win32のUnixのteeコマンドがあります。 http://unxutils.sourceforge.net/ または http://getgnuwin32.sourceforge.net/ を参照してください。

90
Brian Rasmussen

これをチェックしてください。 wintee

Cygwinは必要ありません。

私はいくつかの問題に遭遇し、報告しました。

また、 unxutils にはtee(cygwinは不要)が含まれているのでチェックしてもかまいませんが、出力EOLはUNIXに似ているので注意してください。

最後になりましたが、PowerShellをお持ちの場合は、Tee-Objectを試すことができます。詳細については、PowerShellコンソールでget-help tee-objectと入力してください。

48
Davor Josipovic

@ tori3852

見つけた

dir > a.txt | type a.txt

うまくいきませんでした(最初の数行のdirリストのみ - ある種のプロセスフォークと2番目の部分、 'type'コマンドがdireリストが完了する前に終了したのではないか?)

dir > z.txt && type z.txt

それがした - シーケンシャルコマンド、2番目が始まる前に1つのコマンド。

43
Andy Welch

簡単な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の両方に保存します。

上記のエラー処理の方法はそれほど多くありません。複数のファイルをサポートすることは実際には必要ないかもしれません。

22
Richard

残念ながら、そのようなことはありません。

Windowsコンソールアプリケーションには、単一の出力ハンドルしかありません。 (STDOUTSTDERRが2つありますが、ここでは関係ありません)>は、通常コンソールハンドルに書き込まれる出力をファイルハンドルにリダイレクトします。

ある種の多重化をしたい場合は、出力を転送できる外部アプリケーションを使用する必要があります。このアプリケーションはファイルとコンソールに再度書き込むことができます。

21
Daniel Rikowski

ちょっと醜いですがこれはうまくいきます:

dir >_ && type _ && type _ > a.txt

他のいくつかのソリューションよりも少し柔軟性があります。ステートメントごとに機能するので、追加して使用することもできます。私はメッセージをログに記録して表示するためにバッチファイルでかなりこれを使います:

ECHO Print line to screen and log to file.  >_ && type _ && type _ >> logfile.txt

はい、ECHOステートメントを繰り返すことができます(画面用に1回とログファイルへの2回目のリダイレクト)。ただし、これはまったく同じように見え、メンテナンス上の問題です。少なくともこの方法では、2箇所でメッセージを変更する必要はありません。

_は単なる短いファイル名なので、バッチファイルの最後で必ず削除する必要があります(バッチファイルを使用している場合)。

18
MTS

mteeはこの目的のために非常にうまく機能する小さなユーティリティです。それは無料で、ソースはオープンです、そしてそれはJust Worksです。

あなたはそれを見つけることができます http://www.commandline.co.uk

出力を表示し、同時にログファイルを作成するためにバッチファイルで使用される構文は次のようになります。

    someprocess | mtee /+ mylogfile.txt

/ +は出力を追加することを意味します。

これは、あなたがmteeをPATHにあるフォルダにコピーしたことを前提としています。

16
Mark

私はBrian Rasmussenに同意します、unxutilsポートはこれをする最も簡単な方法です。 Batch Files /彼の スクリプトページ Rob van der Woudeには、MSの使用に関する豊富な情報が記載されています。 -DOSおよびCMDコマンド私は彼があなたの問題に対するネイティブな解決策を持っているのではないかと考え、そこを掘り下げた後、私は TEE.BAT を見つけました。ティーの。それはかなり複雑に見えるバッチファイルです、そして私の傾向はまだunxutilsポートを使うことでしょう。

9
Steve Crane

あなたのウィンドウズ環境パスにcygwinがあるなら、あなたは使うことができます:

 dir > a.txt | tail -f a.txt
8
jkdba

Saxon Druceの 優れた回答 について少し詳しく説明します。

すでに述べたように、現在のディレクトリにある実行可能ファイルの出力を次のようにリダイレクトできます。

powershell ".\something.exe | tee test.txt"

ただし、これはstdouttest.txtに記録するだけです。 stderrも記録されません。

明白な解決策はこのようなものを使うことでしょう:

powershell ".\something.exe 2>&1 | tee test.txt"

ただし、これはすべてのsomething.exesには効果がありません。 something.exeの中には2>&1を引数として解釈して失敗するものがあります。正しい解決策は、代わりにsomething.exeとそのスイッチと引数をアポストロフィで囲むことです。

powershell ".\something.exe --switch1 --switch2 … arg1 arg2 …" 2>&1 | tee test.txt
8
アリスター

dir 1>a.txt 2>&1 | type a.txt

これはSTDOUTとSTDERRの両方をリダイレクトするのに役立ちます。

6
rashok

私も同じ解決策を探していました、少し試した後、私はコマンドプロンプトでそれを達成することに成功しました。これが私の解決策です:

@Echo off
for /f "Delims=" %%a IN (xyz.bat) do (
%%a > _ && type _ && type _ >> log.txt
)
@Echo on

それはどんなPAUSEコマンドでも捕らえます。

4
Koder101

コンソールへの出力の送信、コンソールログへの追加、現在のコマンドからの出力の削除

dir  >> usb-create.1 && type usb-create.1 >> usb-create.log | type usb-create.1 && del usb-create.1
4
Dennis

このような何かはあなたが必要なことをするべきですか?

%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
3
Richard K

これは私が他の答えの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
)
3
Ed Radke

これは非常に古いトピックですが、以前の回答では、バッチで書かれたリアルタイムのティーの完全な実装はありません。以下の私の解決策は、パイプ処理されたコマンドからの出力を取得するためだけに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");
3
Aacini
@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

これにより、現在の日時を含むログファイルが作成され、プロセス中にコンソール行を表示できます。

2
7thSphere

これは以前のMTSによる answer のバリエーションですが、他の人にとって役立つかもしれない機能をいくつか追加しています。私が使用した方法は次のとおりです。

  • コマンドは変数として設定され、コード全体で後で使用でき、set _Temp_Msg_Cmd= を使用してコマンドウィンドウに出力し、ログファイルに追加できます。
    • コマンドがエスケープされました リダイレクト キャロット^文字を使用して、コマンドが最初に評価されないようにしました
  • %~n0_temp.txtと呼ばれる実行中のバッチファイルに似たファイル名で一時ファイルが作成されます。このファイルは、 コマンドラインパラメーター拡張構文%~n0を使用してバッチファイルの名前を取得します。
  • 出力は別のログファイル%~n0_log.txtに追加されます

コマンドのシーケンスは次のとおりです。

  1. 出力およびエラーメッセージは一時ファイル^> %~n0_temp.txt 2^>^&1に送信されます
  2. 一時ファイルの内容は次の両方になります。
    • ログファイルに追加^& type %~n0_temp.txt ^>^> %~n0_log.txt
    • コマンドウィンドウへの出力^& type %~n0_temp.txt
  3. メッセージを含む一時ファイルは削除されます^& 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%

2
ClearBlueSky85

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

エラーメッセージのリダイレクト

コマンドは、コマンドラインで直接入力するのではなく、解釈される文字列であるため、キャレット(^)はそれらの後のシンボルをエスケープするためにあります。

1
Had To Ask

"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
1
Cody Barnes

別の方法としては、プログラム内で標準出力を標準エラー出力に変換します。

javaでは:

System.setOut(new PrintStream(new TeeOutputStream(System.out, System.err)));

次に、dosバッチファイルで、Java program > log.txtを入力します。

標準出力はログファイルに出力され、標準エラー出力(同じデータ)がコンソールに表示されます。

0
The Coordinator

もう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
0
user3726414

私はほとんどのマシンに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

原油と未試験。

0
DannyK

UNIXと同じです。

dir | tee a.txt

Windows XPでは動作しますが、mksntをインストールする必要があります。

ファイルに追加するだけでなく、プロンプトにも表示されます。

0
user2346926

これはリアルタイムで動作しますが、やや醜いパフォーマンスも遅くなります。十分にテストされていません。

@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
0
djangofan

出力を表示してファイルにリダイレクトする方法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.
0
P M

バッチファイルがファイルにリダイレクトされている場合でも、画面上に実際に表示されるものが必要な場合は、以下の手順に従ってください。デバイス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

0