Class: File
- Defined in:
- lib/core/facets/file/ext.rb,
lib/core/facets/file/null.rb,
lib/core/facets/file/write.rb,
lib/core/facets/file/append.rb,
lib/core/facets/file/create.rb,
lib/core/facets/file/rewrite.rb,
lib/core/facets/file/rootname.rb,
lib/core/facets/file/sanitize.rb,
lib/core/facets/file/atomic_id.rb,
lib/core/facets/file/read_list.rb,
lib/core/facets/file/split_all.rb,
lib/core/facets/file/split_root.rb,
lib/core/facets/file/writelines.rb,
lib/core/facets/file/atomic_open.rb,
lib/core/facets/file/common_path.rb,
lib/core/facets/file/read_binary.rb,
lib/core/facets/file/atomic_write.rb,
lib/standard/facets/yaml/file.rb
Class Method Summary collapse
-
.append(file, str) ⇒ Object
Append to a file.
- .atomic_id ⇒ Object
-
.atomic_open(file_name, mode = "r", temp_dir = nil, &block) ⇒ Object
Same as ‘File.open`, but acts on a temporary copy of named file, copying the file back to the original on completion.
-
.atomic_write(file_name, temp_dir = nil) {|temp_file| ... } ⇒ Object
Write to a file atomically.
-
.common_path(*paths) ⇒ Object
Given an array of path strings, find the longest common prefix path.
-
.create(path, str = '', &blk) ⇒ Object
Creates a new file, or overwrites an existing file, and writes a string into it.
-
.ext(filename, new_ext = nil) ⇒ Object
Takes a file name string and returns or changes its extension.
-
.null ⇒ Object
Platform dependent null device.
-
.read_binary(fname) ⇒ Object
Read in a file as binary data.
-
.read_list(filepath, options = {}) ⇒ Object
Reads in a file, removes blank lines and removes lines starting with ‘#’ and then returns an array of all the remaining lines.
-
.rewrite(name, mode = "") ⇒ Object
Opens a file as a string and writes back the string to the file at the end of the block.
-
.rewrite!(name, mode = "") ⇒ Object
In place version of #rewrite.
-
.rootname(path) ⇒ Object
Returns only the first portion of the directory of a file path name.
-
.sanitize(filename) ⇒ Object
Cleans up a filename to ensure it will work on a filesystem.
-
.split_all(path) ⇒ Object
Splits a file path into an array of individual path components.
-
.split_root(path) ⇒ Object
Return the head of path from the rest of the path.
-
.write(path, data) ⇒ Object
Writes the given data to the given path and closes the file.
-
.writelines(path, data) ⇒ Object
Writes the given array of data to the given path and closes the file.
-
.yaml?(file) ⇒ Boolean
Same as ‘YAML.file?(file)`.
Class Method Details
.append(file, str) ⇒ Object
Append to a file.
CREDIT: George Moschovitis
7 8 9 10 11 |
# File 'lib/core/facets/file/append.rb', line 7 def self.append(file, str) File.open(file, 'ab') { |f| f << str } end |
.atomic_id ⇒ Object
4 5 6 7 |
# File 'lib/core/facets/file/atomic_id.rb', line 4 def self.atomic_id @atomic_id ||= 0 @atomic_id += 1 end |
.atomic_open(file_name, mode = "r", temp_dir = nil, &block) ⇒ Object
Same as ‘File.open`, but acts on a temporary copy of named file, copying the file back to the original on completion.
13 14 15 16 17 18 19 20 21 22 23 24 |
# File 'lib/core/facets/file/atomic_open.rb', line 13 def self.atomic_open(file_name, mode="r", temp_dir=nil, &block) temp_dir = temp_dir || Dir.tmpdir temp_file = Tempfile.new("#{atomic_id}-" + basename(file_name), temp_dir) if File.exist?(file_name) FileUtils.cp(file_name, temp_file) end open(temp_file, mode, &block) FileUtils.cp(temp_file, file_name) end |
.atomic_write(file_name, temp_dir = nil) {|temp_file| ... } ⇒ Object
Write to a file atomically. Useful for situations where you don’t want other processes or threads to see half-written files.
File.atomic_write("important.txt") do |file|
file.write("hello")
end
If your temporary directory is not on the same filesystem as the file you’re trying to write, you can provide a different temporary directory.
File.atomic_write("important.txt", "tmp") do |file|
file.write("hello")
end
NOTE: This method is not a common core extension and is not loaded automatically when using require 'facets'
.
CREDIT: David Heinemeier Hansson
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/core/facets/file/atomic_write.rb', line 32 def self.atomic_write(file_name, temp_dir=nil) temp_dir = temp_dir || Dir.tmpdir temp_file = Tempfile.new(basename(file_name), temp_dir) yield temp_file temp_file.close begin ## Get original file permissions old_stat = stat(file_name) rescue Errno::ENOENT ## No old permissions, write a temp file to determine the defaults check_name = join(dirname(file_name), ".permissions_check.#{Thread.current.object_id}.#{Process.pid}.#{rand(1000000)}") open(check_name, "w") { } old_stat = stat(check_name) unlink(check_name) end ## Overwrite original file with temp file FileUtils.mv(temp_file.path, file_name) ## Set correct permissions on new file chown(old_stat.uid, old_stat.gid, file_name) chmod(old_stat.mode, file_name) end |
.common_path(*paths) ⇒ Object
Given an array of path strings, find the longest common prefix path.
6 7 8 9 10 11 12 13 14 15 |
# File 'lib/core/facets/file/common_path.rb', line 6 def self.common_path(*paths) return paths.first if paths.length <= 1 arr = paths.sort f = arr.first.split('/') l = arr.last.split('/') i = 0 i += 1 while f[i] == l[i] && i <= f.length f.slice(0, i).join('/') end |
.create(path, str = '', &blk) ⇒ Object
Creates a new file, or overwrites an existing file, and writes a string into it. Can also take a block just like File#open, which is yielded after the string is writ.
str = 'The content for the file'
File.create('myfile.txt', str)
CREDIT: George Moschovitis
13 14 15 16 17 18 |
# File 'lib/core/facets/file/create.rb', line 13 def self.create(path, str='', &blk) open(path, 'wb') do |f| f << str blk.call(f) if blk end end |
.ext(filename, new_ext = nil) ⇒ Object
Takes a file name string and returns or changes its extension.
Without a new extension argument, returns the extension of the file name. In this respect #ext is like #extname, but unlike #extname it does not include the dot prefix.
With a new extension argument, changes the exension of the file name to the new extension and returns it.
Examples
File.ext('file.rb') # => 'rb'
File.ext('file.rb', 'txt') # => 'file.txt'
File.ext('file.rb', '.txt') # => 'file.txt'
File.ext('file.rb', '') # => 'file'
This method can be used with String#file for more object-oriented notation:
'file.rb'.file.ext('txt') # => 'file.txt'
CREDIT: Lavir the Whiolet
25 26 27 28 29 30 31 32 33 |
# File 'lib/core/facets/file/ext.rb', line 25 def self.ext(filename, new_ext=nil) old_ext = extname(filename) if new_ext == nil old_ext.sub(/^\./, '') else new_ext = '.' + new_ext unless (new_ext.empty? || new_ext[0,1] == '.') filename.chomp(old_ext) + new_ext end end |
.null ⇒ Object
Platform dependent null device.
CREDIT: Daniel Burger
7 8 9 10 11 12 13 14 15 16 17 18 |
# File 'lib/core/facets/file/null.rb', line 7 def self.null case RUBY_PLATFORM when /mswin/i 'NUL' when /amiga/i 'NIL:' when /openvms/i 'NL:' else '/dev/null' end end |
.read_binary(fname) ⇒ Object
Read in a file as binary data.
Assuming we had a binary file ‘binary.dat’.
File.read_binary('binary.dat')
CREDIT: George Moschovitis
11 12 13 14 15 |
# File 'lib/core/facets/file/read_binary.rb', line 11 def self.read_binary(fname) open(fname, 'rb') do |f| return f.read end end |
.read_list(filepath, options = {}) ⇒ Object
Reads in a file, removes blank lines and removes lines starting with ‘#’ and then returns an array of all the remaining lines.
Thr remark indicator can be overridden via the :omit:
option, which can be a regualar expression or a string that is match against the start of a line.
CREDIT: Trans
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/core/facets/file/read_list.rb', line 12 def self.read_list(filepath, ={}) chomp = [:chomp] omit = case [:omit] when Regexp omit when nil /^\s*\#/ else /^\s*#{Regexp.escape(omit)}/ end list = [] readlines(filepath).each do |line| line = line.strip.chomp(chomp) next if line.empty? next if omit === line list << line end list end |
.rewrite(name, mode = "") ⇒ Object
Opens a file as a string and writes back the string to the file at the end of the block.
Returns the number of written bytes or nil
if the file wasn’t modified.
Note that the file will even be written back in case the block raises an exception.
Mode can either be “b” or “+” and specifies to open the file in binary mode (no mapping of the plattform’s newlines to “n” is done) or to append to it.
Assuming we had a file ‘message.txt’ and had a binary file ‘binary.dat’.
# Reverse contents of "message.txt"
File.rewrite("message.txt") { |str| str.reverse }
# Replace "foo" by "bar" in "binary.dat".
File.rewrite("binary.dat", "b") { |str| str.gsub("foo", "bar") }
IMPORTANT: The old version of this method required in place modification of the file string. The new version will write whatever the block returns instead!!!
CREDIT: George Moschovitis
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/core/facets/file/rewrite.rb', line 30 def self.rewrite(name, mode = "") #:yield: unless block_given? raise(ArgumentError, "Need to supply block to File.rewrite") end if mode.is_a?(Numeric) then flag, mode = mode, "" mode += "b" if flag & File::Constants::BINARY != 0 mode += "+" if flag & File::Constants::APPEND != 0 else mode.delete!("^b+") end old_str = open(name, "r#{mode}") { |file| file.read } #rescue "" old_str = old_str.clone begin new_str = yield(old_str) ensure if old_str != new_str open(name, "w#{mode}") { |file| file.write(new_str) } end end end |
.rewrite!(name, mode = "") ⇒ Object
In place version of #rewrite. This version of method requires that the string be modified in place within the block.
# Reverse contents of "message"
File.rewrite("message.txt") { |str| str.reverse! }
# Replace "foo" by "bar" in "binary"
File.rewrite("binary.dat", "b") { |str| str.gsub!("foo", "bar") }
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/core/facets/file/rewrite.rb', line 64 def self.rewrite!(name, mode = "") #:yield: unless block_given? raise(ArgumentError, "Need to supply block to File.rewrite") end if mode.is_a?(Numeric) then flag, mode = mode, "" mode += "b" if flag & File::Constants::BINARY != 0 mode += "+" if flag & File::Constants::APPEND != 0 else mode.delete!("^b+") end old_str = open(name, "r#{mode}") { |file| file.read } #rescue "" new_str = old_str.clone begin yield(new_str) ensure if old_str != new_str open(name, "w#{mode}") { |file| file.write(new_str) } end end end |
.rootname(path) ⇒ Object
12 13 14 15 16 17 18 19 20 |
# File 'lib/core/facets/file/rootname.rb', line 12 def self.rootname(path) # -- this should be fairly robust path_re = Regexp.new('[' + Regexp.escape(File::Separator + %q{\/}) + ']') head, _ = path.split(path_re, 2) return '.' if path == head return '/' if head.empty? return head end |
.sanitize(filename) ⇒ Object
10 11 12 13 14 15 |
# File 'lib/core/facets/file/sanitize.rb', line 10 def self.sanitize(filename) filename = File.basename(filename.gsub("\\", "/")) # work-around for IE filename.gsub!(/[^a-zA-Z0-9\.\-\+_]/,"_") filename = "_#{filename}" if filename =~ /^\.+$/ filename end |
.split_all(path) ⇒ Object
Splits a file path into an array of individual path components. This differs from File.split
, which divides the path into only two parts, directory path and basename.
File.split_all("a/b/c") #=> ['a', 'b', 'c']
CREDIT: Trans
11 12 13 14 15 16 |
# File 'lib/core/facets/file/split_all.rb', line 11 def self.split_all(path) head, tail = File.split(path) return [tail] if head == '.' || tail == '/' return [head, tail] if head == '/' return split_all(head) + [tail] end |
.split_root(path) ⇒ Object
Return the head of path from the rest of the path.
File.split_root('etc/xdg/gtk') #=> ['etc', 'xdg/gtk']
7 8 9 10 |
# File 'lib/core/facets/file/split_root.rb', line 7 def self.split_root(path) path_re = Regexp.new('[' + Regexp.escape(File::Separator + %q{\/}) + ']') path.split(path_re, 2) end |
.write(path, data) ⇒ Object
Writes the given data to the given path and closes the file. This is done in binary mode, complementing IO.read
in standard Ruby.
str = 'The content for the file'
File.write('write.txt', str)
Returns the number of bytes written.
CREDIT: Gavin Sinclair
15 16 17 18 19 |
# File 'lib/core/facets/file/write.rb', line 15 def self.write(path, data) File.open(path, "wb") do |file| return file.write(data) end end |
.writelines(path, data) ⇒ Object
Writes the given array of data to the given path and closes the file. This is done in binary mode, complementing IO.readlines
in standard Ruby.
Note that readlines
(the standard Ruby method) returns an array of lines with newlines intact, whereas writelines
uses puts
, and so appends newlines if necessary. In this small way, readlines
and writelines
are not exact opposites.
data = ['The content', ['for the file']]
File.writelines('writelines.txt', data)
Returns number of lines written.
CREDIT: Noah Gibbs, Gavin Sinclair
19 20 21 22 23 24 |
# File 'lib/core/facets/file/writelines.rb', line 19 def self.writelines(path, data) File.open(path, "wb") do |file| file.puts(data) end data.size end |