Module: FileUtils

Defined in:
lib/batch-kit/core_ext/file_utils.rb

Overview

Re-opens the FileUtils module in the Ruby standard library to add new functionality.

Class Method Summary collapse

Class Method Details

.archive(*paths) ⇒ Object

Archive existing files at paths, where paths is one or more Dir#glob patterns. Archiving consists of renaming files to include a timestamp in the file name. This permits multiple copies of the same file to exist in a single directory. The timestamp is created from the last modification date of the file being archived.

The last argument passed may be an options Hash, which can be used to change the default behaviour. Valid options are:

Parameters:

  • paths (Array<String|Hash>)

    A list of paths to be archived. If the last item passed to the method is a Hahs, it is treated as an an options hash.

Options Hash (*paths):

  • :archive_dir (String)

    The directory in which to place archived files. If not specified, archived files are placed in the same directory.

  • :archive_days (Fixnum)

    The number of days for which to keep archived files. Defaults to nil, meaning there is no maximum number of days.

  • :archive_copies (Fixnum)

    The maximum number of copies to keep of an archived file. Defaults to 10.



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/batch-kit/core_ext/file_utils.rb', line 33

def archive(*paths)
    if paths.last.is_a?(Hash)
        options = paths.pop
    else
        options = {archive_copies: 10}
    end
    archive_dir = options[:archive_dir] || @archive_dir
    archive_copies = options[:archive_copies]
    if archive_copies && 1 > archive_copies
        raise ArgumentError, ":archive_copies option must be positive"
    end
    archive_days = options[:archive_days]
    if archive_days && 1 > archive_days
        raise ArgumentError, ":archive_days option must be positive"
    end
    cutoff_date = archive_days && (Date.today - archive_days)

    FileUtils.mkdir_p(archive_dir) rescue nil if archive_dir

    # Create archives of files that match the patterns in +paths+
    archive_count = 0
    Dir[*paths].each do |file_name|
        next if file_name =~ /\d{8}.\d{6}(?:\.[^.]+)?$/
        File.rename(file_name, '%s/%s.%s%s' % [
                        archive_dir || File.dirname(file_name),
                        File.basename(file_name, File.extname(file_name)),
                        File.mtime(file_name).strftime('%Y%m%d.%H%M%S'),
                        File.extname(file_name)
                    ]) rescue next
        archive_count += 1
    end

    if archive_copies || cutoff_date
        # Find all copies of each unique file matching +paths+
        purge_sets = Hash.new{ |h, k| h[k] = [] }
        folders = archive_dir ? [archive_dir] : paths.map{ |path| File.dirname(path) }.uniq
        folders.each do |folder|
            Dir["#{folder}/*.????????.??????.*"].each do |path|
                if path =~ /^(.+)\.\d{8}\.\d{6}(\.[^.]+)?$/
                    purge_sets["#{$1}#{$2}"] << path
                end
            end
        end

        # Now purge the oldest archives, such that we keep a maximum of
        # +archive_copies+, and no file older than +cutoff_date+.
        purge_sets.each do |orig_name, old_files|
            old_files.sort!
            old_size = old_files.size
            purge_files = []
            if archive_copies && old_size > archive_copies
                purge_files = old_files.slice!(0, old_size - archive_copies)
            end
            if cutoff_date
                vold_files = old_files.reject! do |path|
                    path =~ /(\d{4})(\d{2})(\d{2})\.\d{6}(?:\.[^.]+)?$/
                    file_date = Date.new($1.to_i, $2.to_i, $3.to_i)
                    file_date >= cutoff_date
                end
                purge_files.concat(vold_files) if vold_files
            end
            if purge_files.size > 0
                FileUtils.rm_f(purge_files) rescue nil
            end
        end
    end
    archive_count
end

.archive_dirObject

Set the default archive directory for use on subsequent calls to #archive.



10
11
12
# File 'lib/batch-kit/core_ext/file_utils.rb', line 10

def archive_dir
  @archive_dir
end

.archive_dir=(value) ⇒ Object

Set the default archive directory for use on subsequent calls to #archive.



10
11
12
# File 'lib/batch-kit/core_ext/file_utils.rb', line 10

def archive_dir=(value)
  @archive_dir = value
end