2010-07-02 63 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