14

batファイル用に記述されたteeコードを使用しようとしていますが、コードに実装するのに問題があります。ティーの問題を解決するためにサードパーティのインストールを使用したくありません。1年以内にコンピューターをフォーマットしてプログラムを再度実行したい場合にコードを機能させたいからです。

私はそれをこのように設定しています:

mycommand.exe | tee.bat -a output.txt

私は別の.batファイルを試してみましたが、元のファイルに関数(優先)として含めることを試みました.batが、役に立たなかったのは次のとおりです。

myprogram.exe | call tee -a output.txt
echo.
echo.
echo.
SET /P restart="Do you want to run again? (1=yes, 2=no): "
if "%restart%"=="1" GOTO LoopStart


::--------------------------------------------------------
::-- Function section starts below here
::--------------------------------------------------------
:tee
:: Check Windows version
IF NOT "%OS%"=="Windows_NT" GOTO Syntax
| 
:: Keep variables local
SETLOCAL

:: Check command line arguments
SET Append=0
IF /I [%1]==[-a] (
    SET Append=1
    SHIFT
)
IF     [%1]==[] GOTO Syntax
IF NOT [%2]==[] GOTO Syntax

:: Test for invalid wildcards
SET Counter=0
FOR /F %%A IN ('DIR /A /B %1 2^>NUL') DO CALL :Count "%%~fA"
IF %Counter% GTR 1 (
    SET Counter=
    GOTO Syntax
)

:: A valid filename seems to have been specified
SET File=%1

:: Check if a directory with the specified name exists
DIR /AD %File% >NUL 2>NUL
IF NOT ERRORLEVEL 1 (
    SET File=
    GOTO Syntax
)

:: Specify /Y switch for Windows 2000 / XP COPY command
SET Y=
VER | FIND "Windows NT" > NUL
IF ERRORLEVEL 1 SET Y=/Y

:: Flush existing file or create new one if -a wasn't specified
IF %Append%==0 (COPY %Y% NUL %File% > NUL 2>&1)

:: Actual TEE
FOR /F "tokens=1* delims=]" %%A IN ('FIND /N /V ""') DO (
    >  CON    ECHO.%%B
    >> %File% ECHO.%%B
)

:: Done
ENDLOCAL
GOTO:EOF


:Count
SET /A Counter += 1
SET File=%1
GOTO:EOF


:Syntax
ECHO.
ECHO Tee.bat,  Version 2.11a for Windows NT 4 / 2000 / XP
ECHO Display text on screen and redirect it to a file simultaneously
ECHO.
IF NOT "%OS%"=="Windows_NT" ECHO Usage:  some_command  ¦  TEE.BAT  [ -a ]  filename
IF NOT "%OS%"=="Windows_NT" GOTO Skip
ECHO Usage:  some_command  ^|  TEE.BAT  [ -a ]  filename
:Skip
ECHO.
ECHO Where:  "some_command" is the command whose output should be redirected
ECHO         "filename"     is the file the output should be redirected to
ECHO         -a             appends the output of the command to the file,
ECHO                        rather than overwriting the file
ECHO.
ECHO Written by Rob van der Woude
ECHO http://www.robvanderwoude.com
ECHO Modified by Kees Couprie
ECHO http://kees.couprie.org
ECHO and Andrew Cameron

実行中のプログラムと対話しながら、コンソール出力をファイルに保存できるように、出力を分割しようとしています。

Teeコマンドを.batで正しく機能させて、出力をファイルとコンソールの両方に分割するにはどうすればよいですか。

4

1 に答える 1

24

パイプ内でバッチ関数を呼び出そうとすると、Windows パイプの仕組みが原因で常に失敗します。Windows は新しい CMD シェルを介してパイプの両側をインスタンス化します。詳細については、 https://stackoverflow.com/a/8194279/1012053を参照してください。

バッチ ティーの Rob van der Woude バージョンはFOR /F、コマンドの結果を読み取るために a を使用するため、機能しない可能性があります。コマンドは、行が読み取られる前に完了するまで実行する必要があります。コマンドの実行中にユーザーの操作が必要な場合、それは機能しません。そのバージョンの tee では、単純に出力をファイルにリダイレクトし、TYPE終了したらそのファイルをリダイレクトすることもできます。明らかにあなたが望むものではありません。

より近づけるピュア バッチのトリックはありますが、ピュア バッチでは解決できない問題が 1 つあります。実行可能ファイルは、新しい行を発行せずに行にプロンプ​​トを表示する場合があります。純粋なネイティブ バッチは常に行全体を読み取ると思います (ストリームの最後を除く)。文字ごとに読み取るバッチメソッドを認識していません。

わずかな修正-SET /Pパイプ入力の部分的な行を読み取ることができますが、堅牢なバッチ ティー ソリューションに使用できないという制限があります。各行がいつ終了するかを確実に知る方法はありません。「行」ごとに 1021 文字に制限されています。各「行」の終わりから制御文字を取り除きます。入力ストリームの最後にいつ到達したかを知る方法はありません。

しかし、簡単な解決策があります。JScript または VBScript はチャンピオンのように機能し、特別なインストールは必要ありません。これは、あなたのために働くはずのハイブリッド JScript/バッチ スクリプトです。JScript は不十分に作成されており、改善の余地がたくさんあります。たとえば、エラー チェックはありません。

スクリプトを として保存しますtee.bat。最初の必須引数は、書き込み先のファイルの名前を指定します。デフォルトでは、ファイルがすでに存在する場合は上書きされます。2 番目の引数が指定されている場合 (値は重要ではありません)、代わりに出力がファイルに追加されます。

@if (@X)==(@Y) @end /* Harmless hybrid line that begins a JScript comment

::--- Batch section within JScript comment that calls the internal JScript ----
@echo off
cscript //E:JScript //nologo "%~f0" %*
exit /b

----- End of JScript comment, beginning of normal JScript  ------------------*/
var fso = new ActiveXObject("Scripting.FileSystemObject");
var mode=2;
if (WScript.Arguments.Count()==2) {mode=8;}
var out = fso.OpenTextFile(WScript.Arguments(0),mode,true);
var chr;
while( !WScript.StdIn.AtEndOfStream ) {
  chr=WScript.StdIn.Read(1);
  WScript.StdOut.Write(chr);
  out.Write(chr);
}

使用法は、あなたが期待するようにかなりです。

command.exe | tee.bat output.txt 1

最後の 1 つの引数は追加モードを強制します。1 以外の任意の値を指定できます

好みに応じて、すべてを 1 つのバッチ スクリプトに入れることができます。

@if (@X)==(@Y) @end /* Harmless hybrid line that begins a JScript comment

::--- Batch section within JScript comment ----------------------------
@echo off

::This block of code handles the TEE by calling the internal JScript code
if "%~1"=="_TEE_" (
  cscript //E:JScript //nologo "%~f0" %2 %3
  exit /b
)

::The rest of your batch script goes here

::This pipes to TEE in append mode
mycommand.exe | "%~f0" _TEE_ output.txt 1

exit /b

----- End of JScript comment, beginning of normal JScript  ------------------*/
var fso = new ActiveXObject("Scripting.FileSystemObject");
var mode=2;
if (WScript.Arguments.Count()==2) {mode=8;}
var out = fso.OpenTextFile(WScript.Arguments(0),mode,true);
var chr;
while( !WScript.StdIn.AtEndOfStream ) {
  chr=WScript.StdIn.Read(1);
  WScript.StdOut.Write(chr);
  out.Write(chr);
}

アップデート

バッチ スクリプトに学術的な関心をお持ちの方のために、DosTipsの非同期ネイティブ バッチ ティー スクリプトに、tee の純粋なネイティブ バッチ バージョンを投稿しました。しかし、このハイブリッド アプローチは、私が好むスクリプト ソリューションです。

于 2012-05-23T11:51:38.040 に答える