耙 - 仅复制已更改的文件

时间:2012-04-26 20:44:04

标签: ruby file copy rake

所以我有一个rake文件,如下所示:

require 'fileutils'

task :copy do
  FileUtils.cp_r 'src', 'target'
end

我怎么能:

  1. 仅复制已更改的文件?
  2. 使:copy任务依赖于src目录,以便只在需要时启动它? :copy => 'src':copy => FileList['src/*'].to_a似乎无效。
  3. 我可以照顾这样的第一个问题:

    task :copy do
        sh 'rsync -ru src/* target'
    end
    

    我想,如果合理的可能,只用红宝石/耙子做这件事。这也有些负责第二个问题,因为如果没有文件发生变化,rsync将不会做任何事情,但我希望rake任务在可能的情况下根本不执行。< / p>

2 个答案:

答案 0 :(得分:3)

为了避免执行任务,Rake需要知道目标和源以及用于确定是否执行任务的规则,以便从源创建目标。

通常,规则是“时间修改”,即如果源比目标更新,则Rake将运行任务。您可以通过提供Proc作为源依赖项来修改它。请参阅“高级规则”下的http://docs.rubyrake.org/user_guide/chapter03.html(但需要进行一些实验才能了解正在发生的事情!)。

所以你的任务必须取决于目标。如果你知道目标不存在,那应该很容易:

task :copy => 'target/' do
  sh 'rsync -ru src/ target'  # trailing slash is significant; target will be created
done

如果目标已存在,则会变得更加复杂。您可以为每个文件定义一个规则,但坦率地说,我只是运行rsync并完成它。 Rsync在本地文件系统上非常快,每次运行它都没什么大不了的。

答案 1 :(得分:0)

这是一个OS独立且纯Ruby的解决方案

class File
  def self.update(src, dst)
    if File.exist? dst
      # skip if src file modification or creation time is same or earlier than target
      return if [File.ctime(src), File.mtime(src)].max <= [File.ctime(dst), File.mtime(dst)].max
    else
      # create target folder if not present
      FileUtils.mkdir_p(File.dirname(dst)) unless File.exist? File.dirname(dst)
    end
    FileUtils.cp(src, dst)
    puts src
  rescue => e
    puts "#{e}\n#{e.backtrace}"
  end
end

File.update source_file, target_file