Module: FileUtils

Defined in:
lib/more/facets/fileutils.rb

Constant Summary collapse

LINKING_SUPPORTED =

CREDIT Jim Weirich

[true]
Win32Exts =
%w{.exe .com .bat .cmd}

Class Method Summary collapse

Class Method Details

.head(filename, lines = 10) ⇒ Object

In block form, yields the first number of ((lines)) of file ((filename)). In non-block form, it returns an array of the first number of ((lines)).

# Returns first 10 lines of 'myfile'
FileUtils.head("myfile")


56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/more/facets/fileutils.rb', line 56

def head(filename,lines=10) #:yield:
  a = []
  IO.foreach(filename){|line|
      break if lines <= 0
      lines -= 1
      if block_given?
        yield line
      else
        a << line
      end
  }
  return a.empty? ? nil : a
end

.safe_ln(*args) ⇒ Object

Attempt to do a normal file link, but fall back to a copy if the link fails. – ++



37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/more/facets/fileutils.rb', line 37

def safe_ln(*args)
  unless LINKING_SUPPORTED[0]
    cp(*args)
  else
    begin
      ln(*args)
    rescue Errno::EOPNOTSUPP
      LINKING_SUPPORTED[0] = false
      cp(*args)
    end
  end
end

.slice(filename, from, to) ⇒ Object

In block form, yields lines ((from))-((to)). In non-block form, returns an array of lines ((from))-((to)).

# Returns lines 8-12 of 'myfile'
FileUtils.body("myfile",8,12)

– Credit goes to Shashank Date, via Daniel Berger. ++



94
95
96
# File 'lib/more/facets/fileutils.rb', line 94

def slice(filename,from,to) #:yield:
  IO.readlines(filename)[from-1..to-1]
end

.tail(filename, lines = 10) ⇒ Object

In block form, yields the last number of ((lines)) of file ((filename)). In non-block form, it returns the lines as an array.

Note that this method slurps the entire file, so I don’t recommend it for very large files. If you want an advanced form of ((tail)), I suggest using file-tail, by Florian Frank (available on the RAA). And no tail -f.

# Returns last 3 lines of 'myfile'
FileUtils.tail("myfile",3)


81
82
83
# File 'lib/more/facets/fileutils.rb', line 81

def tail(filename,lines=10) #:yield
  IO.readlines(filename).reverse[0..lines-1].reverse
end

.wc(filename, option = 'all') ⇒ Object

With no arguments, returns a four element array consisting of the number of bytes, characters, words and lines in filename, respectively.

Valid options are bytes, characters (or just ‘chars’), words and lines.

# Return the number of words in 'myfile'
FileUtils.wc("myfile",'words')


109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/more/facets/fileutils.rb', line 109

def wc(filename,option='all')
  option.downcase!
  valid = %w/all bytes characters chars lines words/

  unless valid.include?(option)
      raise "Invalid option: '#{option}'"
  end

  n = 0
  if option == 'lines'
      IO.foreach(filename){ n += 1 }
      return n
  elsif option == 'bytes'
      File.open(filename){ |f|
        f.each_byte{ n += 1 }
      }
      return n
  elsif option == 'characters' || option == 'chars'
      File.open(filename){ |f|
        while f.getc
            n += 1
        end
      }
      return n
  elsif option == 'words'
      IO.foreach(filename){ |line|
        n += line.split.length
      }
      return n
  else
      bytes,chars,lines,words = 0,0,0,0
      IO.foreach(filename){ |line|
        lines += 1
        words += line.split.length
        chars += line.split('').length
      }
      File.open(filename){ |f|
        while f.getc
            bytes += 1
        end
      }
      return [bytes,chars,words,lines]
  end
end

.whereis(prog, path = ) ⇒ Object

In block form, yields each ((program)) within ((path)). In non-block form, returns an array of each ((program)) within ((path)). Returns ((nil)) if not found.

On the MS Windows platform, it looks for executables ending with .exe, .bat and .com, which you may optionally include in the program name.

File.whereis("ruby") -> ['/usr/local/bin/ruby','/opt/bin/ruby']


170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# File 'lib/more/facets/fileutils.rb', line 170

def whereis(prog, path=ENV['PATH']) #:yield:
  dirs = []
  path.split(File::PATH_SEPARATOR).each{|dir|
      # Windows checks against specific extensions
      if File::ALT_SEPARATOR
        if prog.include?('.')
            f = File.join(dir,prog)
            if File.executable?(f) && !File.directory?(f)
              if block_given?
                  yield f.gsub(/\//,'\\')
              else
                  dirs << f.gsub(/\//,'\\')
              end
            end
        else
            Win32Exts.find_all{|ext|
              f = File.join(dir,prog+ext)
              if File.executable?(f) && !File.directory?(f)
                  if block_given?
                    yield f.gsub(/\//,'\\')
                  else
                    dirs << f.gsub(/\//,'\\')
                  end
              end
            }
        end
      else
        f = File.join(dir,prog)
        # Avoid /usr/lib/ruby, for example
        if File.executable?(f) && !File.directory?(f)
            if block_given?
              yield f
            else
              dirs << f
            end
        end
      end
  }
  dirs.empty? ? nil : dirs
end

.which(prog, path = ) ⇒ Object

Looks for the first occurrence of program within path.

On the MS Windows platform, it looks for executables ending with .exe, .bat and .com, which you may optionally include in the program name. Returns nil if not found.

– The which() method was adopted from Daniel J. Berger, via PTools which in in turn was adopted fromt the FileWhich code posted by Michael Granger on www.rubygarden.org. ++



222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'lib/more/facets/fileutils.rb', line 222

def which(prog, path=ENV['PATH'])
  path.split(File::PATH_SEPARATOR).each {|dir|
    # Windows checks against specific extensions
    if File::ALT_SEPARATOR
      ext = Win32Exts.find{|ext|
        if prog.include?('.') # Assume extension already included
          f = File.join(dir,prog)
        else
          f = File.join(dir,prog+ext)
        end
        File.executable?(f) && !File.directory?(f)
      }
      if ext
        # Use backslashes, not forward slashes
        if prog.include?('.') # Assume extension already included
          f = File.join( dir, prog ).gsub(/\//,'\\')
        else
          f = File.join( dir, prog + ext ).gsub(/\//,'\\')
        end
        return f
      end
    else
      f = File.join(dir,prog)
      # Avoid /usr/lib/ruby, for example
      if File.executable?(f) && !File.directory?(f)
        return File::join( dir, prog )
      end
    end
  }
  nil
end