首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >批处理脚本,重新格式化cli应用程序的输出

批处理脚本,重新格式化cli应用程序的输出
EN

Stack Overflow用户
提问于 2012-05-09 02:05:08
回答 2查看 2K关注 0票数 3

我有一个非常小的批处理脚本,其中提取了相当多的文件。该脚本将与压缩数据一起传递给其他用户。

现在我的问题是,这个压缩工具正在向cmd窗口输出大量数据。我认为这会让很多用户感到困惑,因为输出真的是“运行”的。它基本上显示了每一行的百分比,以及它如何以哪种速度(CPU和HDD)解压。许多令人困惑的数据,没有人需要看到。现在我真的不喜欢抑制程序的所有输出,在我看来,给用户关于解压已经达到多大程度的反馈是很重要的。那么,有没有可能重定向输出,只读取输出的前三位数,并在一行中将其传递给用户?因此,用户只看到一个前进的百分比(在一行中),而不是每秒使用所有这些数据的20个新行?

这里有一个目前的例子:http://i.imgur.com/5w5LH.png压缩工具是SREP,我的操作系统Win 7 x64。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-05-09 03:11:34

下面是一个简单的批处理/JScript混合脚本,我认为它可以做你想要的事情。

show3.bat

代码语言:javascript
运行
复制
@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();

用法:

代码语言:javascript
运行
复制
yourCommand | show3

脚本可以简化为纯JScript,但使用起来就不那么方便了:

show3.js

代码语言:javascript
运行
复制
while( !WScript.StdIn.AtEndOfStream ) {
  WScript.StdOut.Write( '\x08\x08\x08' + WScript.StdIn.ReadLine().substr(0,3) );
}
WScript.StdOut.WriteLine();

用法:

代码语言:javascript
运行
复制
yourCommand | cscript //nologo show3.js

编辑正如jeb所说,你应该不需要任何修改就可以使用这个解决方案。

我采用了jeb答案中的一些概念,并将整个过程合并到一个混合脚本中。不需要独立的"show3“文件。

代码语言:javascript
运行
复制
@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“文件。它粗略地模拟了您为压缩程序描述的输出行为。

代码语言:javascript
运行
复制
@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的解决方案。我去掉了临时文件,改为使用管道。

代码语言:javascript
运行
复制
@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测试,以忽略任何前导或尾随空格。这应该会使代码更加健壮。

票数 4
EN

Stack Overflow用户

发布于 2012-05-09 03:35:21

如果你使用windows批处理,这是可以做到的,但这并不简单,因为你通常会使用FOR/F-Loop来做这件事。

for /f "delims=" %%a in (7z packit ...) do ...

这里的问题是,for循环将首先收集所有数据,并在处理输出的任何行之前等待7z结束。

唯一的方法是重定向输出,并同时扫描它。

但要做到这一点,你需要第二个线程(充其量在同一个cmd窗口中)。

这样的东西就可以完成这项工作

代码语言:javascript
运行
复制
@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
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10504003

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档