从FileUtils获取执行的命令?

时间:2010-07-02 06:10:48

标签: ruby rubygems

:verbose标志传递给FileUtils命令时,该命令将打印到STDOUT。有没有办法捕获命令,以便可以记录或在其他地方使用?

2 个答案:

答案 0 :(得分:4)

如果您查看FileUtils的来源,它会使用以下方法来执行详细输出:

def fu_output_message(msg)   #:nodoc:
  @fileutils_output ||= $stderr
  @fileutils_label  ||= ''
  @fileutils_output.puts @fileutils_label + msg
end

即。它正在将消息写入@fileutils_output,默认情况下使用的是$stderr。似乎没有一种方法可以改变@fileutils_output,但你可以添加一个:

module FileUtils
  def FileUtils.fileutils_output=(new_out)
    @fileutils_output = new_out
  end
end

然后,如果您想将命令捕获到文件中,您可以这样做:

my_fu_log = open('fu_log.log', 'w')
FileUtils.fileutils_output = my_fu_log
# FileUtils operations with :verbose => true here
my_fu_log.close
FileUtils.fileutils_output = $stderr # restore writing to stderr if you want

或者如果你想用字符串获取它们,你可以这样做:

log = StringIO.new
FileUtils.fileutils_output = log
# FileUtils operations with :verbose => true here
# commands are in log.string 

此外,还有一个模块FileUtils::Verbose基本上包含FileUtils(因此具有相同的方法),但默认选项为:verbose => true所以如果您想要捕获大量命令,可以使用它而不是每次都指定选项。 (您需要以与上面相同的方式将fileutils_output=方法添加到此模块。)

<强>替代

正如Joshua在下面的评论中所说,另一种方法是重新分配$stderr,但正如他所说,这确实意味着所有写入stderr(不仅仅是FileUtils)的内容都会被重定向。如果所有FileUtils操作都是一次性发生而没有其他任何内容,那么这可能不是问题。所以有些东西:

orig_stderr = $stderr # keep reference to original stderr
$stderr = my_fu_log
# use FileUtils here
$stderr = orig_stderr # restore stderr

最后,如果您需要更多控制权,可以重新开启FileUtils并覆盖fu_output_message(msg)

答案 1 :(得分:0)

要添加到Mike的答案中(因为我无法评论),如果您想将输出作为字符串输出,我创建了此包装器def

def fileutil_out
    out = StringIO.new
    FileUtils.fileutils_output = out
    yield
    return out.string
end

mylog.info fileutil_out { FileUtils.chmod_R(0664, 'file.txt', :verbose => isVerbose) }

我最终没有使用它,因为之后我想恢复到@fileutils_output ||= $stderr