3

かなりの量のファイルを抽出する非常に小さなバッチ スクリプトがあります。このスクリプトは、圧縮されたデータとともに他のユーザーに配信されることを意図しています。

今私の問題は、この圧縮ツールが大量のデータを cmd ウィンドウに出力していることです。出力が実際に「実行中」であるため、これは多くのユーザーを混乱させると思います。基本的に、各行のパーセンテージと、どの速度 (CPU と HDD) でどのように解凍されたかを示します。誰も見る必要のない多くの紛らわしいデータ。現在、プログラムのすべての出力を抑制するのは本当に好きではありません。私の意見では、解凍がどれだけ進んだかについてユーザーにフィードバックを与えることが重要です。出力をリダイレクトして、その出力の最初の 3 桁だけを読み取り、それを 1 行でユーザーに配信することは可能でしょうか? ユーザーは、このすべてのデータで毎秒 20 行の新しい行ではなく、(1 行で) 進行するパーカンテージのみを確認しますか?

現時点での例を次に示します。 http://i.imgur.com/5w5LH.png 圧縮ツールは SREP、私の OS Win 7 x64 です。

4

2 に答える 2

5

Windowsバッチを使用する場合は実行できますが、通常はFOR / Fループで実行するため、簡単ではありません。

for /f "delims=" %%a in (7z packitのように...問題) do ...
はここにあります。forループは最初にすべてのデータを収集し7z、出力の任意の行を処理する前に終了を待ちます。

唯一の方法は、出力をリダイレクトし、同時にスキャンすることです。
ただし、これを行うには、2番目のスレッドが必要です(せいぜい同じcmdウィンドウ内)。

このような何かが仕事をするだろう

@echo off
echo start
setlocal EnableDelayedExpansion
if "%1"=="internal" goto :readThread
start /b cmd /c ""%~f0" internal"

rem *** myPacker pack here and redirect the output
del archive.7z
del output.tmp
start "title" /b /wait cmd /c  "%ProgramFiles%\7-Zip\7z" u  archive \tempx\*.rtf \tempx\*.pdf ^> output.tmp
echo EOF>>output.tmp
echo ENDE
:waitForEnd
(
> lock (
  rem
) || goto :waitForEnd
) 2> nul
exit /b

:readThread

for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"
echo ####!cr!x
echo(
<output.tmp ( 
    echo ## before
    call :readData 2> lock
    echo after
)
exit /b

:readData
set "var="
set /p var=
if "!var!"=="EOF" exit /b
if defined var (
  <nul set /p ".=Processing files, currently at !var:~0,4!!CR!"
)
goto :readData
于 2012-05-08T19:35:21.327 に答える
4

これが単純なハイブリッドバッチ/JScriptスクリプトで、あなたが望むことを実行できると思います。

show3.bat

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

::: Batch part ::::
@cscript //nologo //e:JScript "%~f0"
@exit /b

*** JScript part ***/
while( !WScript.StdIn.AtEndOfStream ) {
  WScript.StdOut.Write( '\x08\x08\x08' + WScript.StdIn.ReadLine().substr(0,3) );
}
WScript.StdOut.WriteLine();

使用法:

yourCommand | show3

スクリプトは純粋なJScriptに簡略化できますが、その場合、使用するのはそれほど便利ではありません。

show3.js

while( !WScript.StdIn.AtEndOfStream ) {
  WScript.StdOut.Write( '\x08\x08\x08' + WScript.StdIn.ReadLine().substr(0,3) );
}
WScript.StdOut.WriteLine();

使用法:

yourCommand | cscript //nologo show3.js

編集jebがコメントしたように、このソリューションを使用するために再作成する必要はありません。

jebの回答にあるいくつかの概念を取り上げ、プロセス全体を1つのハイブリッドスクリプトにまとめました。スタンドアロンの「show3」ファイルは必要ありません。

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

:: ***** Batch part ******
@echo off

REM whatever batch code you need goes here

yourCommand | cscript //nologo //e:JScript "%~f0"

REM whatever batch code you need goes here

exit /b

****** JScript part ******/
while( !WScript.StdIn.AtEndOfStream ) {
  WScript.StdOut.Write( '\x08\x08\x08' + WScript.StdIn.ReadLine().substr(0,3) );
}
WScript.StdOut.WriteLine();

yourCommand使用している圧縮コマンドは何でもかまいません。コメントに基づくと、必要なyourCommand 2>&1出力がstdoutではなくstderrに出力される場合は、使用する必要があるようです。

テスト用に「yourCommand.bat」ファイルを作成しました。これは、圧縮プログラムについて説明した出力動作を大まかにエミュレートします。

@echo off
for /l %%A in (1 1 100) do (
  echo %%A   "I don't want to see this quoted text"
  for /l %%B in (1 1 50000) do rem
)

最後に、本当に純粋なバッチソリューションが必要な場合は、jebのソリューションを大幅に簡略化しました。一時ファイルを削除し、代わりにパイプを使用しました。

@echo off
if "%~1"==":show3" goto :show3
REM whatever batch code you need goes here

(yourCommand & echo EOF) | "%~f0" :show3

REM whatever batch code you need goes here
exit /b

:show3
setlocal enableDelayedExpansion
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"
:read
set "ln="
set /p "ln="
if not defined ln goto :read
for /f "tokens=1* delims= " %%A in ("!ln!") do if "%%A%%B" equ "EOF" (
  echo(
  exit /b
)
<nul set /p "=!ln:~0,3!   !cr!"
goto :read

編集-先頭または末尾のスペースを無視するようにEOFテストを変更しました。これにより、コードがより堅牢になります。

于 2012-05-08T19:11:34.187 に答える