我有一个非常小的批处理脚本,其中提取了相当多的文件。该脚本将与压缩数据一起传递给其他用户。
现在我的问题是,这个压缩工具正在向cmd窗口输出大量数据。我认为这会让很多用户感到困惑,因为输出真的是“运行”的。它基本上显示了每一行的百分比,以及它如何以哪种速度(CPU和HDD)解压。许多令人困惑的数据,没有人需要看到。现在我真的不喜欢抑制程序的所有输出,在我看来,给用户关于解压已经达到多大程度的反馈是很重要的。那么,有没有可能重定向输出,只读取输出的前三位数,并在一行中将其传递给用户?因此,用户只看到一个前进的百分比(在一行中),而不是每秒使用所有这些数据的20个新行?
这里有一个目前的例子:http://i.imgur.com/5w5LH.png压缩工具是SREP,我的操作系统Win 7 x64。
发布于 2012-05-09 03:11:34
下面是一个简单的批处理/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答案中的一些概念,并将整个过程合并到一个混合脚本中。不需要独立的"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
可以是您正在使用的任何压缩命令。根据您的评论,如果您希望输出打印到stderr而不是stdout,则可能必须使用yourCommand 2>&1
。
我已经创建了一个用于测试的"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-09 03:35:21
如果你使用windows批处理,这是可以做到的,但这并不简单,因为你通常会使用FOR/F-Loop来做这件事。
如for /f "delims=" %%a in (
7z packit ...) do ...
这里的问题是,for循环将首先收集所有数据,并在处理输出的任何行之前等待7z
结束。
唯一的方法是重定向输出,并同时扫描它。
但要做到这一点,你需要第二个线程(充其量在同一个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
https://stackoverflow.com/questions/10504003
复制相似问题