web-dev-qa-db-ja.com

コンソール出力をバットスクリプトのファイルにエコーして送信するにはどうすればよいですか?

タスクを実行し、出力をテキストファイルに送信するバッチスクリプトがあります。コンソールウィンドウにも出力を表示する方法はありますか?

例えば:

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

dirの出力をコンソールウィンドウに表示する方法と、テキストファイルに出力する方法はありますか?

130
JamesEggers

いいえ、純粋なリダイレクトではできません。
しかし、いくつかのトリック( tee.bat など)を使えばできます。

リダイレクトについて少し説明しようと思います。

> fileまたは<fileで10個のストリームの1つをリダイレクトします
リダイレクトがコマンドの前後にある場合は重要ではないため、これらの2行はほぼ同じです。

dir > file.txt
> file.txt dir

この例のリダイレクトは、1>のショートカットにすぎません。つまり、ストリーム1(STDOUT)がリダイレクトされます。
したがって、2> err.txtのような番号を前に付けてストリームをリダイレクトできます。また、複数のストリームを1つにリダイレクトすることもできますライン。

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

この例では、「標準出力」はfiles.txtに格納され、すべてのエラーはerr.txtに格納され、stream3はnothing.txtに格納されます(DIRはストリーム3を使用しません)。
Stream0はSTDINです
Stream1はSTDOUTです
Stream2はSTDERRです
Stream3-9は使用されません

しかし、同じストリームを複数回リダイレクトしようとするとどうなりますか?

dir > files.txt > two.txt

「1つしか存在できません」、それは常に最後の1つです!
したがって、dir> two.txtと等しくなります

ストリームを別のストリームにリダイレクトするという1つの追加の可能性があります。

dir 1>files.txt 2>&1 

2>&1stream2をstream1にリダイレクトし、1> files.txtリダイレクトallfiles.txt.
順序はここで重要です!

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

異なっています。最初のものはすべて(STDOUTとSTDERR)をNULにリダイレクトします。
しかし、2行目はSTDOUTをNULにリダイレクトし、STDERRを「空の」STDOUTにリダイレクトします。

1つの結論として、なぜオタヴィオデシオとアンディノルマンクスの例がうまくいかないのかは明らかです。

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

どちらもstream1を2回リダイレクトしようとしますが、「1つしか存在できません」であり、常に最後のものです。
だからあなたは

command 1>&1
dir 1>&2

また、最初のサンプルでは、​​stream1からstream1へのリダイレクトは許可されていません(あまり役に立ちません)。

それが役に立てば幸い。

211
jeb

次のように、WindowsバージョンのUNIX teeコマンド( http://unxutils.sourceforge.net にあります)を使用します。

mycommand > tee outpu_file.txt

STDERR出力も必要な場合は、次を使用します。
2>&1は、STDERR出力をSTDOUT(プライマリストリーム)に結合します。

mycommand 2>&1 | tee output_file.txt
32
atn

リアルタイムでの出力が必要ない場合(つまり、プログラムが書き込み中)、追加することができます

type windows-dir.txt

その行の後。

9
Mark Pim

私のために働いた解決策は: dir> a.txt | type a.txt

はい、単一のコマンド出力をコンソール(画面)とファイルに表示する方法があります。あなたの例を使用して、使用...

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

詳細な説明:

FORコマンドは、コマンドまたはテキストの出力を変数に解析し、複数回参照できるようにします。

DIR /Bなどのコマンドの場合、以下の例に示すように、単一引用符で囲みます。 DIR /Bテキストを目的のコマンドに置き換えます。

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

テキストを表示するには、次の例に示すように、テキストを二重引用符で囲みます。

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

...そして行の折り返しを...

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

出力をコンソール(画面)のみで行い、他の時間をファイルのみに送信し、他の時間を両方に送信する場合は、変数を使用してFORループの "DO"句を指定します(以下に示す%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
6
Amazinate
command > file >&1
3
Otávio Décio

出力ファイルを置き換える代わりに追加する場合は、使用することができます

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

または

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

私はatnの答えが好きですが、 wintee としてダウンロードするのは簡単ではありませんでしたユーティリティ)。これについては、 Windowsコマンドプロンプト出力の表示とファイルへのリダイレクト に対するdavorの回答から学びました。ここでは、UNIXユーティリティへの参照も見つかります。

1
sage

Cmd画面とログの両方へのリアルタイム出力を処理できる単純なC#コンソールを作成しました

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

バッチファイルの使用法は、Unixのteeの使用方法と同じです。

foo | tee xxx.log

そして、ここにコンパイルするツールがない場合のTee.exeを含むリポジトリがあります https://github.com/iamshiao/Tee

1
蕭為元

私のオプションはこれでした:

メッセージを受け取り、コンソールとログファイルの両方に送信するプロセスを自動化するサブルーチンを作成します。

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

メッセージに変数を追加する場合、サブルーチンに送信する前に必ず引用符を削除してください。そうしないと、バッチが台無しになります。もちろん、これはエコーに対してのみ機能します。

1
JPZ

「Tomas R」が提供するソリューションは、OPの質問に最適に機能し、ネイティブで利用できます。

試してください:chkdsk c:> output.txt | output.txtと入力します

このコマンドの出力には、ファイルにシリアル出力される完了率が含まれているため、少し乱雑に見えます(つまり、進行中にテキストが追加されます)。これは、STDOUT(画面)に出力されるビットには発生しません。リダイレクトせずに同じコマンドを実行するだけの場合はどうでしょう。

0
J0N