2010-07-02 86 views

回答

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

这是一个很好的答案。你可以做的另一件事是将$ stderr重定向到你自己的对象,然后你不必打开FileUtils类。当然,您将捕获打印到$ stderr的非FileUtils方法的结果。 – 2010-07-02 08:00:44

+0

@Joshua Yep,你是对的。我实际上是通过重新分配'$ stdout'开始的,但是当它不起作用时(因为它是写给'$ stderr'的),我最终深入研究了'FileUtils'代码并提出了上面的问题。 – mikej 2010-07-02 08:14:11

+0

非常好!非常感谢您的明确答复(并在此进行讨论!)正是我需要的:) – 2010-07-03 01:03:18

0

要添加到小李的答案(因为我不能评论),我创造了这个包装,如果你想获得输出字符串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