Ruby 如何在 Rake 的 task 中使用 ruby-progressbar

enalix · 2016年08月25日 · 最后由 pathbox 回复于 2016年09月05日 · 2418 次阅读

代码如下:

pb = ProgressBar.create(title: "标题")  # 创建进度条
task :abc do  # 定义一个普通的任务
  dir_ary = Dir["*"]  # 获取当前目录下所有的文件
  pb.total = dir_ary.size  # 设置进度条的长度
  Dir["*"].each do |f|
    pb.increment  # 进度加1
    rm -rf f
  end
  pb.reset  # 重置进度条
end

ruby-progressbar是一个广泛使用的终端进度条显示,我之前使用过,代码中即最通常的用法。

但问题是,在shell中执行rake abc, 它一定会输出rm -rf xxx, 即它执行过的命令。且每次输出都会刷新stdout缓冲区。

而终端条的基本原理是,在输出进度时,stdout缓冲区不能刷新,不然会看到:进度条每加 1, 则换行,加 1, 换行,头疼。

问题:如何让rake执行任务时,不输出也不刷新缓冲区。应该有代码可以配置,但我个人没有仔细研究过rake.

关于在别的进程执行shell命令,使用类似openxsystem等不考虑。代码中的rmFileUtils模块中的方法。

还有>/dev/null就更不考虑了,因为任务中的puts显示输出,我还是需要的。

求大神解答。我个人最近看来要细看下rake了,如果有答案也会贴出。

===================================================================================

问题更新:

今天又看了点东西,探索了下,这问题其实涉及两个方面:

  • Raketask如何写,或者如何配置,能达到rake -s task_name命令行执行的效果,即默认静默执行
  • ruby-progressbar似乎在写文件的迭代中,会不断的换行

第一个问题,我还不知道,但似乎定位了第二个问题。下面代码可执行,可反映问题。

pb = ProgressBar.create(title: "下载", total: 10, format: '%t (%c %C) |%B| %p%%')
(1..10).each do |n| 
  pb.increment 
  open("hello/#{n}", 'w') do |f|
    f.write "hello"
  end
  sleep  1  # 写文件的速度太快, 刻意等1秒
end

结果就是进度每加 1, 则换行。

就个人有限的知道来看,似乎是跟write方法有关,猜测此方法可能给stdout\n换行符了。具体不解。

非常抱歉,第一段代码,似乎不能重现问题。

方法 1. pb = ProgressBar... 放到 task block 里面就行了

方法 2. 在 Rakefile 里加入:

require 'progress_bar/core_ext/enumerable_with_progress'

就有 Enumerable, Array, Hash, Range #each_with_progress 可以用了

如果不需要 task 依赖,可以不用 rake。

捕获 rm rf 输出呢?

` 包含的命令不会输出到 stdout,为什么要拘泥于 FileUtils 来给自己找麻烦呢?不要执着于 一切都用 Ruby 来写

#1 楼 @lithium4010 那个progress_bar是哪个gem的?

#5 楼 @enalix https://github.com/paul/progress_bar 好吧可能我搞错了 不过这个真的挺好用的

可以写 ruby 脚本,require‘ruby-progressbar’,用 rails runner 运行

需要 登录 后方可回复, 如果你还没有账号请 注册新账号