Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursive copy excluding folders matching filter

Tags:

ruby

rake

I am trying to create a Rake method to copy all files from one location to another but exclude all folders that are SVN folders including their files.

This is the method in a module called Filesystem I started with, but can't figure out if it will work or what the missing code is. The module has the following require:

require "fileutils"

Method:

def FileSystem.CopyFilesWithoutSVN(source, target)
  # will copy files from source folder to target folder excluding .svn folders
  FileUtils.cp_r  Dir.glob( source ).reject{|entry| entry =~ missingCode }, target
end

So for example the source would be:

folderA
  folderB
    file1.cs
    file2.cs
    file3.cs
    file4.cs
    .svn
        fileA.base
        fileB.base
.svn
  fileC.base
  fileD.base
folderC 
    file5.cs

then the target would contain the following after the copy:

folderA
  folderB
    file1.cs
    file2.cs
    file3.cs
    file4.cs
folderC
    file5.cs  
like image 938
Jeff2001 Avatar asked Aug 02 '12 11:08

Jeff2001


4 Answers

The easiest solution for this kind of thing is to use rsync, provided your software is running on a system where it is installed.

`rsync -a --exclude=.svn #{source}/ #{target}`

You probably also want to add the --delete option to delete existing files in the target tree that are no longer present within the source tree.

As a bonus, it will only copy new or modified files the next time you run it. You can also use it to copy files across systems over the net. See the documentation for more.


If you don't have rsync available, or don't want to make your code dependent on it, you can use the following method:

require 'find'
require 'fileutils'

def copy_without_svn(source_path, target_path)    
  Find.find(source_path) do |source|
    target = source.sub(/^#{source_path}/, target_path)
    if File.directory? source
      Find.prune if File.basename(source) == '.svn'
      FileUtils.mkdir target unless File.exists? target
    else
      FileUtils.copy source, target
    end
  end
end

Find is part of the Ruby standard library.

like image 93
Lars Haugseth Avatar answered Oct 13 '22 13:10

Lars Haugseth


what you want is something like

.reject {|f| /.svn/.match(f) != nil }
like image 33
Andrew Avatar answered Oct 13 '22 13:10

Andrew


You are only looking for name matches in the root directory, you should be looking in each directory recursively. I would say it is easier to just copy everything over, and then remove the SVN files by running something like this in the newly created directory:

`find #{target} -name ".svn" -type d -exec rm -rf {} \;`

So you method would look something like this:

module FileSystem
  def self.CopyFilesWithoutSVN(source, target)
    # will copy files from source folder to target folder excluding .svn folders
    FileUtils.cp_r  Dir.glob( source ).reject{|entry| entry =~ missingCode }, target
    `find #{target} -name ".svn" -type d -exec rm -rf {} \;`
  end
end
like image 45
Achilles Avatar answered Oct 13 '22 13:10

Achilles


find and rsync are not great because plenty of systems don't have either of those. It's not too hard to do it one file at a time:

FileUtils.mkdir_p(target) unless File.exists? target
Dir.glob("#{source}/**/*").reject{|f| f['.svn']}.each do |oldfile|
  newfile = target + oldfile.sub(source, '')
  File.file?(oldfile) ? FileUtils.copy(oldfile, newfile) : FileUtils.mkdir(newfile)
end
like image 1
pguardiario Avatar answered Oct 13 '22 14:10

pguardiario