2

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

require 'fileutils'

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

我怎样才能:

  1. 只复制已更改的文件?
  2. 使:copy任务对src目录具有依赖性,以便仅在需要时启动?:copy => 'src'并且:copy => FileList['src/*'].to_a似乎不起作用。

我可以像这样处理第一个问题:

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

如果可能的话,我想只用 ruby​​ / rake 来做这件事。这在某种程度上也解决了第二个问题,因为rsync如果没有文件更改,则不会做任何事情,但我希望 rake 任务尽可能不执行。

4

2 回答 2

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 在本地文件系统上非常快,每次运行它都没什么大不了的。

于 2012-05-21T10:40:24.453 回答
1

这是一个独立于操作系统且纯 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
于 2016-04-19T15:00:53.113 回答