All methods from FileTest and all predicates from File are included
Path's low-level implementation based on Pathname
The list of loaders. See {Path.register_loader}.
@private
The version of the gem. Set here to avoid duplication and allow introspection.
Returns the path as a String. {path} is implemented for better readability (file.path instead of file.to_s) and as an accessor. {to_path} is implemented so Path objects are usable with open, etc. {to_str} is implemented so Path objects are usable with open, etc with Ruby 1.8 (it is not defined in Ruby 1.9).
Returns the path as a String. {path} is implemented for better readability (file.path instead of file.to_s) and as an accessor. {to_path} is implemented so Path objects are usable with open, etc. {to_str} is implemented so Path objects are usable with open, etc with Ruby 1.8 (it is not defined in Ruby 1.9).
Returns the path as a String. {path} is implemented for better readability (file.path instead of file.to_s) and as an accessor. {to_path} is implemented so Path objects are usable with open, etc. {to_str} is implemented so Path objects are usable with open, etc with Ruby 1.8 (it is not defined in Ruby 1.9).
Returns the path as a String. {path} is implemented for better readability (file.path instead of file.to_s) and as an accessor. {to_path} is implemented so Path objects are usable with open, etc. {to_str} is implemented so Path objects are usable with open, etc with Ruby 1.8 (it is not defined in Ruby 1.9).
Configures the behavior of {Path#+}. The default is :warning.
Path + :defined # aliased to Path#/ Path + :warning # calls Path#/ but warns Path + :error # not defined Path + :string # like String#+. Warns if $VERBOSE (-w)
@param config [:defined, :warning, :error, :string] the configuration value
# File lib/path/implementation.rb, line 48 def Path.+(config) unless [:defined, :warning, :error, :string].include? config raise ArgumentError, "Invalid configuration: #{config.inspect}" end if @plus_configured raise "Path.+ has already been called: #{@plus_configured}" end remove_method :+ if method_defined? :+ case config when :defined alias :+ :/ when :warning def +(other) warn 'Warning: use of deprecated Path#+ as Path#/: ' << "#{inspect} + #{other.inspect}\n#{caller.first}" self / other end when :error # nothing to do, the method has been removed when :string def +(other) warn 'Warning: use of deprecated Path#+ as String#+: ' << "#{inspect} + #{other.inspect}\n#{caller.first}" if $VERBOSE Path(to_s + other.to_s) end end @plus_configured = caller.first end class << self alias :configure_plus :+ end @plus_configured = nil # Initialization Path.configure_plus(:warning) @plus_configured = nil # Let the user overrides this default configuration # @!method +(other) # The behavior depends on the configuration with Path.{Path.+}. # It might behave as {Path#/}, String#+, give warnings, # or not be defined at all. # Joins paths. # # path0.join(path1, ..., pathN) # # is the same as # path0 / path1 / ... / pathN def join(*paths) result = nil paths.reverse_each { |path| result = Path.new(path) / result return result if result.absolute? } self / result end # #relative_path_from returns a relative path from the argument to the # receiver. They must be both relative or both absolute. # # #relative_path_from doesn't access the filesystem. It assumes no symlinks. # # @raise [ArgumentError] if it cannot find a relative path: # Either the base is relative and contains '..' (in that case you can expand # both paths) or the paths are absolutes and on different drives (Windows). def relative_path_from(base_directory) dest = clean.path base = Path.new(base_directory).clean.path dest_prefix, dest_names = split_names(dest) base_prefix, base_names = split_names(base) unless SAME_PATHS[dest_prefix, base_prefix] raise ArgumentError, "different prefix: #{self.inspect} and #{base_directory.inspect}" end while d = dest_names.first and b = base_names.first and SAME_PATHS[d, b] dest_names.shift base_names.shift end raise ArgumentError, "base_directory has ..: #{base_directory.inspect}" if base_names.include? '..' # the number of names left in base is the ones we have to climb names = base_names.fill('..').concat(dest_names) return Path.new('.') if names.empty? Path.new(*names) end alias :relative_to :relative_path_from alias :% :relative_path_from # @private module Helpers private # remove the leading . of +ext+ if present. def pure_ext(ext) ext = ext.to_s and ext.start_with?('.') ? ext[1..-1] : ext end # add a leading . to +ext+ if missing. Returns '' if +ext+ is empty. def dotted_ext(ext) ext = ext.to_s and (ext.empty? or ext.start_with?('.')) ? ext : ".#{ext}" end end include Helpers extend Helpers private def init @path = validate(@path) taint if @path.tainted? @path.freeze freeze end def validate(path) raise ArgumentError, "path contains a null byte: #{path.inspect}" if path.include? "\00"" path.gsub!(File::ALT_SEPARATOR, '/') if File::ALT_SEPARATOR path = File.expand_path(path) if path.start_with? '~' path end # chop_basename(path) -> [pre-basename, basename] or nil def chop_basename(path) base = File.basename(path) if base.empty? or base == '/' return nil else return path[0, path.rindex(base)], base end end def is_absolute?(path) path.start_with?('/') or (path =~ /\A[a-zA-Z]:\// and is_root?($&)) end def is_root?(path) chop_basename(path) == nil and path.include?('/') end # split_names(path) -> prefix, [name, ...] def split_names(path) names = [] while r = chop_basename(path) path, basename = r names.unshift basename if basename != '.' end return path, names end def prepend_prefix(prefix, relnames) relpath = File.join(*relnames) if relpath.empty? File.dirname(prefix) elsif prefix.include? '/' # safe because File.dirname returns a new String add_trailing_separator(File.dirname(prefix)) << relpath else prefix + relpath end end def has_trailing_separator?(path) !is_root?(path) and path.end_with?('/') end def add_trailing_separator(path) # mutates path path << '/' unless path.end_with? '/' path end def del_trailing_separator(path) if r = chop_basename(path) pre, basename = r pre + basename elsif %{/+\z} =~ path $` + File.dirname(path)[%{/*\z}] else path end end # remove '..' segments since root's parent is root def remove_root_parents(prefix, names) names.shift while names.first == '..' if is_root?(prefix) end # Clean the path simply by resolving and removing excess "." and ".." entries. # Nothing more, nothing less. def cleanpath_aggressive pre = @path names = [] while r = chop_basename(pre) pre, base = r if base == '.' # do nothing, it can be ignored elsif names.first == '..' and base != '..' # base can be ignored as we go back to its parent names.shift else names.unshift base end end remove_root_parents(pre, names) Path.new(prepend_prefix(pre, names)) end def cleanpath_conservative path = @path pre, names = split_names(path) remove_root_parents(pre, names) if names.empty? Path.new(File.dirname(pre)) else names << '.' if names.last != '..' and File.basename(path) == '.' result = prepend_prefix(pre, names) if names.last != '.' and names.last != '..' and has_trailing_separator?(path) Path.new(add_trailing_separator(result)) else Path.new(result) end end end def plus(prefix, rel) return rel if is_absolute?(rel) _, names = split_names(rel) loop do # break if that was the last segment break unless r = chop_basename(prefix) prefix, name = r next if name == '.' # break if we can't resolve anymore if name == '..' or names.first != '..' prefix << name break end names.shift end remove_root_parents(prefix, names) has_prefix = chop_basename(prefix) if names.empty? has_prefix ? prefix : File.dirname(prefix) else suffix = File.join(*names) has_prefix ? File.join(prefix, suffix) : prefix + suffix end end end
Marshal loading.
# File lib/path/identity.rb, line 149 def self._load path self.new(path) end
{Path} to the directory of this file: +Path(__FILE__).dir+.
# File lib/path.rb, line 20 def dir(from = nil) from ||= caller # this can not be moved as a default argument, JRuby optimizes it file(from).dir end
{Path} to the current file +Path(__FILE__)+.
# File lib/path.rb, line 12 def file(from = nil) from ||= caller # this can not be moved as a default argument, JRuby optimizes it # v This : is there to define a group without capturing new(from.first.rpartition(/:\d+(?:$|:in )/).first).expand end
Returns the current working directory as a Path. See Dir.getwd.
# File lib/path/dir.rb, line 16 def Path.getwd new Dir.getwd end
Returns or yields Path objects. See Dir.glob. @yieldparam [Path] path
# File lib/path/dir.rb, line 7 def glob(pattern, flags = 0) if block_given? Dir.glob(pattern, flags) { |f| yield new(f) } else Dir.glob(pattern, flags).map(&Path) end end
JSON loading.
# File lib/path/identity.rb, line 139 def self.json_create json new json['data'] end
A matcher responding to #===. Useful for case clauses, grep, etc. See {Path.like?}.
case obj when Path.like then Path(obj) # ... end
# File lib/path/identity.rb, line 36 def like @like ||= begin matcher = Object.new def matcher.===(object) Path.like?(object) end matcher end end
Creates a new Path. If multiple arguments are given, they are joined with File.join. The path will have File::ALT_SEPARATOR replaced with '/' and if it begins with a '~', it will be expanded (using File.expand_path). Accepts an Array of Strings, a Tempfile, anything that respond to path, to_path or to_str with a String and defaults to calling to_s.
@param parts [Array<String>, Tempfile, to_path, path, to_str, to_s] the path-like object(s)
# File lib/path/identity.rb, line 57 def initialize(*parts) path = parts.size > 1 ? File.join(*parts) : parts.first @path = case path when Tempfile @_tmpfile = path # We would not want it to be GC'd path.path.dup when String path.dup else if path.respond_to? :to_path and String === path.to_path path.to_path.dup elsif path.respond_to? :path and String === path.path path.path.dup elsif path.respond_to? :to_str and String === path.to_str path.to_str.dup else path.to_s.dup end end init end
Creates a new Path. See {initialize}.
# File lib/path/identity.rb, line 6 def new(*args) if args.size == 1 and Path === args.first args.first else super(*args) end end
A {Path} to the null device on the current platform.
# File lib/path.rb, line 39 def null new case RbConfig::CONFIG['host_os'] when /mswin|mingw/ then 'NUL' when /amiga/ then 'NIL:' when /openvms/ then 'NL:' else '/dev/null' end end
Registers a new loader (a block which will be called with the Path to load) for the given extensions (either with the leading dot or not)
Path.register_loader('.marshal') { |file| Marshal.load file.read }
@yieldparam [Path] path
# File lib/path/load.rb, line 13 def self.register_loader(*extensions, &loader) extensions.each { |ext| LOADERS[pure_ext(ext)] = loader } end
{Path} relative to the directory of this file.
# File lib/path.rb, line 26 def relative(path, from = nil) from ||= caller # this can not be moved as a default argument, JRuby optimizes it new(path).expand dir(from) end
Requires all .rb files recursively under directory (or the current file's directory if not given).
The order of requires is alphabetical, but files having the same basename as a directory are required before files in this directory.
# in bar.rb Path.require_tree # require in this order: # foo.rb # foo/ext.rb # foo/sub.rb
@param directory [String] the directory to search,
or the current file's directory.
@option options [Array<String>] :except ([])
a list of prefixes to ignore, relative to +directory+.
# File lib/path/require_tree.rb, line 22 def self.require_tree(directory = nil, options = {}) directory, options = nil, directory if Hash === directory source = Path.file(caller) directory = Path.relative(directory || source.dir, caller) except = options[:except] || [] directory.glob('**/*.rb').reject { |path| except.any? { |prefix| (path % directory).path.start_with?(prefix) } }.sort! { |a,b| if b.inside?(a.rm_ext) -1 elsif a.inside?(b.rm_ext) +1 else a <=> b end }.each { |file| require file.path unless source == file } end
@yieldparam [Path] tmpdir
# File lib/path.rb, line 83 def tmpchdir(prefix_suffix = nil, *rest) tmpdir do |dir| dir.chdir do yield dir end end end
@yieldparam [Path] tmpdir
# File lib/path.rb, line 69 def tmpdir(prefix_suffix = nil, *rest) require 'tmpdir' dir = new Dir.mktmpdir(prefix_suffix, *rest) if block_given? begin yield dir ensure FileUtils.remove_entry_secure(dir) rescue nil end end dir end
@yieldparam [Path] tmpfile
# File lib/path.rb, line 54 def tmpfile(basename = '', tmpdir = nil, options = nil) tempfile = Tempfile.new(basename, *[tmpdir, options].compact) file = new tempfile if block_given? begin yield file ensure tempfile.close! end end file end
A class constructor.
%w[foo bar].map(&Path) # == [Path('foo'), Path('bar')]
# File lib/path/identity.rb, line 18 def to_proc lambda { |path| new(path) } end
A {Path} to the home directory of user (defaults to the current user). The form with an argument (user) is not supported on Windows.
# File lib/path.rb, line 33 def ~(user = '') new("~#{user}") end
# File lib/path/implementation.rb, line 60 def +(other) warn 'Warning: use of deprecated Path#+ as Path#/: ' << "#{inspect} + #{other.inspect}\n#{caller.first}" self / other end
Path#/ appends a path fragment to this one to produce a new Path.
p = Path.new("/usr") # => #<Path /usr>
p / "bin/ruby" # => #<Path /usr/bin/ruby>
p / "/etc/passwd" # => #<Path /etc/passwd>
This method doesn't access the file system, it is pure string manipulation.
# File lib/path/implementation.rb, line 36 def /(other) Path.new(plus(@path, other.to_s)) end
Provides for comparing paths, case-sensitively.
# File lib/path/identity.rb, line 98 def <=>(other) return nil unless Path === other @path.tr('/', "\00"") <=> other.path.tr('/', "\00"") end
Compare this path with other. The comparison is string-based. Be aware that two different paths (foo.txt and ./foo.txt) can refer to the same file.
# File lib/path/identity.rb, line 92 def == other Path === other and @path == other.path end
Marshal dumping.
# File lib/path/identity.rb, line 144 def _dump level @path end
Whether a path is absolute.
# File lib/path/predicates.rb, line 5 def absolute? is_absolute?(@path) end
Adds ext as an extension to path. Handle both extensions with or without leading dot. No-op if ext is empty?.
Path('file').add_extension('txt') # => #<Path file.txt>
# File lib/path/parts.rb, line 46 def add_extension(ext) return self if ext.to_s.empty? Path.new @path+dotted_ext(ext) end
# File lib/path/implementation.rb, line 212 def add_trailing_separator(path) # mutates path path << '/' unless path.end_with? '/' path end
Appends contents to self. See IO.write or +IO#write+.
# File lib/path/io.rb, line 69 def append(contents, open_args = {}) open_args[:mode] = 'a' IO.write(@path, contents, open_args) end
Iterates over each element in the given path in ascending order.
Path.new('/path/to/some/file.rb').ascend { |v| p v }
#<Path /path/to/some/file.rb>
#<Path /path/to/some>
#<Path /path/to>
#<Path /path>
#<Path />
Path.new('path/to/some/file.rb').ascend { |v| p v }
#<Path path/to/some/file.rb>
#<Path path/to/some>
#<Path path/to>
#<Path path>
It doesn't access actual filesystem. @yieldparam [Path] path
# File lib/path/parts.rb, line 125 def ascend return to_enum(:ascend) unless block_given? path = @path yield self while r = chop_basename(path) path, = r break if path.empty? yield Path.new(del_trailing_separator(path)) end end
Returns last access time. See File.atime.
# File lib/path/file.rb, line 5 def atime File.atime(@path) end
Ascends the parents until it finds the given path.
Path.backfind('lib') # => the lib folder
It accepts an XPath-like context:
Path.backfind('.[.git]') # => the root of the repository
# File lib/path.rb, line 111 def backfind(path) condition = path[/\[(.*)\]$/, 1] || '' path = $` unless condition.empty? result = ancestors.find { |ancestor| (ancestor/path/condition).exist? } result/path if result end
basename(extname)
# File lib/path/parts.rb, line 10 def base basename(extname) end
Returns the last component of the path. See File.basename.
# File lib/path/parts.rb, line 5 def basename(*args) Path.new(File.basename(@path, *args)) end
Returns all the bytes from the file, or the first N if specified. See IO.binread.
# File lib/path/io.rb, line 26 def binread(*args) IO.binread(@path, *args) end
Writes contents to self. See IO.binwrite.
# File lib/path/io.rb, line 58 def binwrite(contents, *open_args) IO.binwrite(@path, contents, *open_args) end
See File.blockdev?.
# File lib/path/file_predicates.rb, line 7 def blockdev? File.blockdev?(@path) end
See File.chardev?.
# File lib/path/file_predicates.rb, line 12 def chardev? File.chardev?(@path) end
Changes the current working directory of the process to self. See Dir.chdir. The recommended way to use it is to use the block form, or not use it all!
# File lib/path/dir.rb, line 85 def chdir(&block) Dir.chdir(@path, &block) end
Returns the children of the directory (files and subdirectories, not recursive) as an array of Path objects. By default, the returned paths will have enough information to access the files. If you set with_directory to false, then the returned paths will contain the filename only.
For example:
pn = Path("/usr/lib/ruby/1.8")
pn.children
# -> [ #<Path /usr/lib/ruby/1.8/English.rb>,
#<Path /usr/lib/ruby/1.8/Env.rb>,
#<Path /usr/lib/ruby/1.8/abbrev.rb>, ... ]
pn.children(false)
# -> [ #<Path English.rb>, #<Path Env.rb>, #<Path abbrev.rb>, ... ]
Note that the results never contain the entries . and .. in the directory because they are not children.
# File lib/path/dir.rb, line 106 def children(with_directory=true) with_directory = false if @path == '.' result = [] Dir.foreach(@path) { |e| next if e == '.' || e == '..' if with_directory result << Path.new(@path, e) else result << Path.new(e) end } result end
Changes permissions of path. See File.chmod.
# File lib/path/file.rb, line 21 def chmod(mode) File.chmod(mode, @path) end
Recusively changes permissions. See FileUtils.chmod_R and File.chmod.
# File lib/path/fileutils.rb, line 88 def chmod_r(mode) FileUtils.chmod_R(mode, @path) end
chop_basename(path) -> [pre-basename, basename] or nil
# File lib/path/implementation.rb, line 169 def chop_basename(path) base = File.basename(path) if base.empty? or base == '/' return nil else return path[0, path.rindex(base)], base end end
Changes the owner and group of the file. See File.chown.
# File lib/path/file.rb, line 31 def chown(owner, group) File.chown(owner, group, @path) end
Recusively changes owner and group. See FileUtils.chown_R and File.chown.
# File lib/path/fileutils.rb, line 93 def chown_r(owner, group) FileUtils.chown_R(owner, group, @path) end
Returns a cleaned version of self with consecutive slashes and useless dots removed. The filesystem is not accessed.
If consider_symlink is true, then a more conservative algorithm is used to avoid breaking symbolic linkages. This may retain more .. entries than absolutely necessary, but without accessing the filesystem, this can't be avoided. See {realpath}.
# File lib/path/implementation.rb, line 18 def clean(consider_symlink = false) consider_symlink ? cleanpath_conservative : cleanpath_aggressive end
Clean the path simply by resolving and removing excess "." and ".." entries. Nothing more, nothing less.
# File lib/path/implementation.rb, line 235 def cleanpath_aggressive pre = @path names = [] while r = chop_basename(pre) pre, base = r if base == '.' # do nothing, it can be ignored elsif names.first == '..' and base != '..' # base can be ignored as we go back to its parent names.shift else names.unshift base end end remove_root_parents(pre, names) Path.new(prepend_prefix(pre, names)) end
# File lib/path/implementation.rb, line 253 def cleanpath_conservative path = @path pre, names = split_names(path) remove_root_parents(pre, names) if names.empty? Path.new(File.dirname(pre)) else names << '.' if names.last != '..' and File.basename(path) == '.' result = prepend_prefix(pre, names) if names.last != '.' and names.last != '..' and has_trailing_separator?(path) Path.new(add_trailing_separator(result)) else Path.new(result) end end end
Copies the file to to. See FileUtils.cp.
# File lib/path/fileutils.rb, line 44 def cp(to) # TODO: remove :preserve when all implement it correctly (r31123) FileUtils.cp(@path, to, :preserve => true) end
Copies the file or directory recursively to the directory to. See FileUtils.cp_r.
# File lib/path/fileutils.rb, line 52 def cp_r(to) FileUtils.cp_r(@path, to) end
Returns last change time (of the directory entry, not the file itself). See File.ctime.
# File lib/path/file.rb, line 11 def ctime File.ctime(@path) end
# File lib/path/implementation.rb, line 217 def del_trailing_separator(path) if r = chop_basename(path) pre, basename = r pre + basename elsif %{/+\z} =~ path $` + File.dirname(path)[%{/*\z}] else path end end
Iterates over each element in the given path in descending order.
Path.new('/path/to/some/file.rb').descend { |v| p v }
#<Path />
#<Path /path>
#<Path /path/to>
#<Path /path/to/some>
#<Path /path/to/some/file.rb>
Path.new('path/to/some/file.rb').descend { |v| p v }
#<Path path>
#<Path path/to>
#<Path path/to/some>
#<Path path/to/some/file.rb>
It doesn't access actual filesystem. @yieldparam [Path] path
# File lib/path/parts.rb, line 102 def descend return to_enum(:descend) unless block_given? ascend.reverse_each { |v| yield v } nil end
See File.directory?.
# File lib/path/file_predicates.rb, line 38 def directory? File.directory?(@path) end
Returns all but the last component of the path.
Don't chain this when the path is relative:
Path('.').dir # => #<Path .>
Use parent instead. See File.dirname.
# File lib/path/parts.rb, line 20 def dirname Path.new(File.dirname(@path)) end
Iterates over the children of the directory (files and subdirectories, not recursive). By default, the yielded paths will have enough information to access the files. If you set with_directory to false, then the returned paths will contain the filename only.
Path("/usr/local").each_child { |f| p f } # =>
#<Path /usr/local/share>
#<Path /usr/local/bin>
#<Path /usr/local/games>
#<Path /usr/local/lib>
#<Path /usr/local/include>
#<Path /usr/local/sbin>
#<Path /usr/local/src>
#<Path /usr/local/man>
Path("/usr/local").each_child(false) { |f| p f } # =>
#<Path share>
#<Path bin>
#<Path games>
#<Path lib>
#<Path include>
#<Path sbin>
#<Path src>
#<Path man>
@yieldparam [Path] child
# File lib/path/dir.rb, line 145 def each_child(with_directory=true, &b) children(with_directory).each(&b) end
Iterates over the entries (files and subdirectories) in the directory.
Path("/usr/local").each_entry { |entry| p entry } # =>
#<Path .>
#<Path ..>
#<Path lib>
#<Path share>
# ...
@deprecated Use {each_child} instead.
This method is deprecated since it is too low level and likely useless in Ruby. But it is there for the sake of compatibility with Dir.foreach and Pathname#each_entry.
@yieldparam [Path] entry
# File lib/path/dir.rb, line 38 def each_entry(&block) Dir.foreach(@path) { |f| yield Path.new(f) } end
Iterates over each component of the path.
Path.new("/usr/bin/ruby").each_filename { |filename| ... }
# yields "usr", "bin", and "ruby".
@yieldparam [String] filename
# File lib/path/parts.rb, line 78 def each_filename return to_enum(__method__) unless block_given? _, names = split_names(@path) names.each { |filename| yield filename } nil end
Iterates over the lines in the file. See IO.foreach. @yieldparam [String] line
# File lib/path/io.rb, line 12 def each_line(*args, &block) IO.foreach(@path, *args, &block) end
Return the entries (files and subdirectories) in the directory. Each Path only contains the filename. The result may contain the current directory #<Path .> and the parent directory #<Path ..>.
Path('/usr/local').entries
# => [#<Path share>, #<Path lib>, #<Path .>, #<Path ..>, <Path bin>, ...]
@deprecated Use {children} instead.
This method is deprecated since it is too low level and likely useless in Ruby. But it is there for the sake of compatibility with Dir.entries (and Pathname#entries).
# File lib/path/dir.rb, line 79 def entries Dir.entries(@path).map(&Path) end
See File.executable?.
# File lib/path/file_predicates.rb, line 17 def executable? File.executable?(@path) end
See File.executable_real?.
# File lib/path/file_predicates.rb, line 22 def executable_real? File.executable_real?(@path) end
See File.exist?.
# File lib/path/file_predicates.rb, line 27 def exist? File.exist?(@path) end
Expands path, making it absolute. If the path is relative, it is expanded with the current working directory, unless dir is given as an argument. See File.expand_path.
# File lib/path/file.rb, line 112 def expand(*args) Path.new(File.expand_path(@path, *args)) end
{extname} without leading dot.
# File lib/path/parts.rb, line 31 def ext ext = extname ext.empty? ? ext : ext[1..-1] end
Returns the extension, with a leading dot. See File.extname.
# File lib/path/parts.rb, line 26 def extname File.extname(@path) end
See File.file?.
# File lib/path/file_predicates.rb, line 44 def file? File.file?(@path) end
Path#find is an iterator to traverse a directory tree in a depth first manner. It yields a Path for each file under "this" directory.
Returns an enumerator if no block is given.
Since it is implemented by find.rb, Find.prune can be used to control the traversal.
If self is ., yielded paths begin with a filename in the current directory, not ./.
@yieldparam [Path] path
# File lib/path/find.rb, line 14 def find return to_enum(__method__) unless block_given? require 'find' if @path == '.' Find.find(@path) { |f| yield Path.new(f.sub(%{\A\./}, '')) } else Find.find(@path) { |f| yield Path.new(f) } end end
Return true if the receiver matches the given pattern. See File.fnmatch?.
# File lib/path/file_predicates.rb, line 148 def fnmatch?(pattern, *args) File.fnmatch?(pattern, @path, *args) end
Returns "type" of file ("file", "directory", etc). See File.ftype.
# File lib/path/file.rb, line 42 def ftype File.ftype(@path) end
Returns or yields Path objects. See Dir.glob. @yieldparam [Path] path
# File lib/path/dir.rb, line 61 def glob(pattern, flags = 0) if block_given? Dir.glob(join(pattern), flags) { |f| yield Path.new(f) } else Dir.glob(join(pattern), flags).map(&Path) end end
See File.grpowned?.
# File lib/path/file_predicates.rb, line 33 def grpowned? File.grpowned?(@path) end
Whether the contents of path and file are identical. See FileUtils.compare_file.
# File lib/path/fileutils.rb, line 99 def has_same_contents?(file) FileUtils.compare_file(@path, file) end
# File lib/path/implementation.rb, line 208 def has_trailing_separator?(path) !is_root?(path) and path.end_with?('/') end
The hash value of the path.
# File lib/path/identity.rb, line 104 def hash @path.hash end
Returns the first bytes bytes of the file. If the file size is smaller than bytes, return the whole contents.
# File lib/path/io.rb, line 91 def head(bytes) read(bytes) end
See File.identical?.
# File lib/path/file_predicates.rb, line 140 def identical?(path) File.identical?(@path, path) end
# File lib/path/implementation.rb, line 153 def init @path = validate(@path) taint if @path.tainted? @path.freeze freeze end
Psych loading.
# File lib/path/identity.rb, line 125 def init_with(coder) @path = coder['path'] init end
Whether self is inside ancestor, such that ancestor is an ancestor of self. This is pure String manipulation. Paths should be absolute. self is considered to be inside itself.
# File lib/path.rb, line 95 def inside? ancestor @path == ancestor.to_s or @path.start_with?("#{ancestor}/") end
A representation of the path.
# File lib/path/identity.rb, line 114 def inspect "#<Path #{@path}>" end
Install file into path (the "prefix", which should be a directory). If file is not same as path/file, replaces it. See FileUtils.install (arguments are swapped).
# File lib/path/fileutils.rb, line 83 def install(file, options = {}) FileUtils.install(file, @path, options) end
# File lib/path/implementation.rb, line 178 def is_absolute?(path) path.start_with?('/') or (path =~ /\A[a-zA-Z]:\// and is_root?($&)) end
# File lib/path/implementation.rb, line 182 def is_root?(path) chop_basename(path) == nil and path.include?('/') end
Joins paths.
path0.join(path1, ..., pathN) # is the same as path0 / path1 / ... / pathN
# File lib/path/implementation.rb, line 94 def join(*paths) result = nil paths.reverse_each { |path| result = Path.new(path) / result return result if result.absolute? } self / result end
Changes permissions of path, not following symlink. See File.lchmod.
# File lib/path/file.rb, line 26 def lchmod(mode) File.lchmod(mode, @path) end
Changes the owner and group of path, not following symlink. See File.lchown.
# File lib/path/file.rb, line 37 def lchown(owner, group) File.lchown(owner, group, @path) end
Path#load helps loading data from various files. JSON and YAML loaders are provided by default. See {Path.register_loader}.
# File lib/path/load.rb, line 22 def load if LOADERS.key? ext LOADERS[ext].call(self) else raise "Unable to load #{self} (unrecognized extension)" end end
Returns the stat of path as a +File::Stat+ object, not following symlink. See File.lstat.
# File lib/path/file.rb, line 72 def lstat File.lstat(@path) end
Creates a hard link to target and returns self.
Raises Errno::EEXIST if self already exist. See File.link (arguments are swapped).
# File lib/path/file.rb, line 50 def make_link(target) File.link(target, @path) self end
Creates a symbolic link to target and returns self.
Raises Errno::EEXIST if self already exist. See File.symlink (arguments are swapped).
# File lib/path/file.rb, line 85 def make_symlink(target) File.symlink(target, @path) self end
Create the referenced directory and returns self. See Dir.mkdir.
# File lib/path/dir.rb, line 43 def mkdir(*args) Dir.mkdir(@path, *args) self end
Creates a full path, including any intermediate directories that don't yet exist. See FileUtils.mkpath.
# File lib/path/fileutils.rb, line 8 def mkpath FileUtils.mkpath(@path) self end
mountpoint? returns true if self points to a mountpoint.
# File lib/path/predicates.rb, line 24 def mountpoint? begin stat1 = lstat stat2 = parent.lstat stat1.dev != stat2.dev or stat1.ino == stat2.ino rescue Errno::ENOENT false end end
Returns last modification time. See File.mtime.
# File lib/path/file.rb, line 16 def mtime File.mtime(@path) end
Moves self to the to directory.
# File lib/path/fileutils.rb, line 74 def mv(to) FileUtils.mv(@path, to) to end
Opens the file for reading or writing. See File.open. @yieldparam [File] file
# File lib/path/io.rb, line 6 def open(*args, &block) File.open(@path, *args, &block) end
See Dir.open. @yieldparam [Dir] dir
# File lib/path/dir.rb, line 55 def opendir(&block) Dir.open(@path, &block) end
The opposite of {inside?}.
# File lib/path.rb, line 100 def outside? ancestor !inside?(ancestor) end
See File.owned?.
# File lib/path/file_predicates.rb, line 59 def owned? File.owned?(@path) end
parent returns the parent directory. This can be chained.
# File lib/path/implementation.rb, line 25 def parent self / '..' end
See File.pipe?.
# File lib/path/file_predicates.rb, line 49 def pipe? File.pipe?(@path) end
# File lib/path/implementation.rb, line 270 def plus(prefix, rel) return rel if is_absolute?(rel) _, names = split_names(rel) loop do # break if that was the last segment break unless r = chop_basename(prefix) prefix, name = r next if name == '.' # break if we can't resolve anymore if name == '..' or names.first != '..' prefix << name break end names.shift end remove_root_parents(prefix, names) has_prefix = chop_basename(prefix) if names.empty? has_prefix ? prefix : File.dirname(prefix) else suffix = File.join(*names) has_prefix ? File.join(prefix, suffix) : prefix + suffix end end
# File lib/path/implementation.rb, line 196 def prepend_prefix(prefix, relnames) relpath = File.join(*relnames) if relpath.empty? File.dirname(prefix) elsif prefix.include? '/' # safe because File.dirname returns a new String add_trailing_separator(File.dirname(prefix)) << relpath else prefix + relpath end end
Returns all data from the file, or the first bytes bytes if specified. See IO.read.
# File lib/path/io.rb, line 19 def read(*args) IO.read(@path, *args) end
See File.readable?.
# File lib/path/file_predicates.rb, line 64 def readable? File.readable?(@path) end
See File.readable_real?.
# File lib/path/file_predicates.rb, line 81 def readable_real? File.readable_real?(@path) end
Returns all the lines from the file. See IO.readlines.
# File lib/path/io.rb, line 36 def readlines(*args) IO.readlines(@path, *args) end
Reads the symbolic link. See File.readlink.
# File lib/path/file.rb, line 56 def readlink Path.new(File.readlink(@path)) end
Returns the real (absolute) path of self in the actual filesystem. The real path doesn't contain symlinks or useless dots.
The last component of the real path can be nonexistent.
# File lib/path/file.rb, line 129 def realdirpath(basedir=nil) Path.new(real_path_internal(false, basedir)) end
Returns the real (absolute) path of self in the actual filesystem not containing symlinks or useless dots.
All components of the path must exist when this method is called.
# File lib/path/file.rb, line 121 def realpath(basedir=nil) Path.new(real_path_internal(true, basedir)) end
Whether a path is relative.
# File lib/path/predicates.rb, line 10 def relative? not absolute? end
relative_path_from returns a relative path from the argument to the receiver. They must be both relative or both absolute.
relative_path_from doesn't access the filesystem. It assumes no symlinks.
@raise [ArgumentError] if it cannot find a relative path:
Either the base is relative and contains '..' (in that case you can expand both paths) or the paths are absolutes and on different drives (Windows).
# File lib/path/implementation.rb, line 111 def relative_path_from(base_directory) dest = clean.path base = Path.new(base_directory).clean.path dest_prefix, dest_names = split_names(dest) base_prefix, base_names = split_names(base) unless SAME_PATHS[dest_prefix, base_prefix] raise ArgumentError, "different prefix: #{self.inspect} and #{base_directory.inspect}" end while d = dest_names.first and b = base_names.first and SAME_PATHS[d, b] dest_names.shift base_names.shift end raise ArgumentError, "base_directory has ..: #{base_directory.inspect}" if base_names.include? '..' # the number of names left in base is the ones we have to climb names = base_names.fill('..').concat(dest_names) return Path.new('.') if names.empty? Path.new(*names) end
Relocates this path somewhere else.
Without a block, this method is a simple shorcut for a longer expression that proves difficult to remember in practice:
to / (self.sub_ext(new_ext) % from)
That is, it relocates the original path to a target folder to appended with the relative path from a source folder from. An optional new extension can also be specified, as it is a common use case.
With a block, the relative path is passed to the block for user update, without the last extension. new_ext is added after (or the original extension if not provided).
from = Path('pictures')
to = Path('output/public/thumbnails')
earth = from / 'nature/earth.jpg'
earth.relocate(from, to)
# => #<Path output/public/thumbnails/nature/earth.jpg>
earth.relocate(from, to, '.png') { |rel|
"#{rel}-200"
}
# => #<Path output/public/thumbnails/nature/earth-200.png>
# File lib/path.rb, line 146 def relocate(from, to, new_ext = ext, &updater) updater ||= lambda { |path| path } renamer = lambda { |rel| Path(updater.call(rel.rm_ext)).add_ext(new_ext) } to / renamer.call(self % from) end
remove '..' segments since root's parent is root
# File lib/path/implementation.rb, line 229 def remove_root_parents(prefix, names) names.shift while names.first == '..' if is_root?(prefix) end
Renames the file and returns the new Path. See File.rename.
# File lib/path/file.rb, line 61 def rename(to) File.rename(@path, to) Path(to) end
Replaces the last extension of path with ext. Handle both extensions with or without leading dot. Removes last extension if ext is empty?.
Path('main.c++').replace_extension('cc') # => #<Path main.cc>
# File lib/path/parts.rb, line 66 def replace_extension(ext) return without_extension if ext.to_s.empty? Path.new(@path[0..-extname.size-1] << dotted_ext(ext)) end
Rewrites contents of self.
Path('file').rewrite { |contents| contents.reverse }
@yieldparam [String] contents @yieldreturn [String] contents to write
# File lib/path/io.rb, line 85 def rewrite write yield read end
Removes the file using FileUtils.rm.
# File lib/path/fileutils.rb, line 24 def rm FileUtils.rm(@path) self end
Removes the file, ignoring errors, using FileUtils.rm_f.
# File lib/path/fileutils.rb, line 30 def rm_f FileUtils.rm_f(@path) self end
Removes the file or directory recursively, ignoring errors, using FileUtils.rm_f.
# File lib/path/fileutils.rb, line 38 def rm_rf FileUtils.rm_rf(@path) self end
Remove the referenced directory. See Dir.rmdir.
# File lib/path/dir.rb, line 49 def rmdir Dir.rmdir(@path) end
Deletes a directory and all beneath it. See FileUtils.rm_r.
# File lib/path/fileutils.rb, line 15 def rmtree # The name "rmtree" is borrowed from File::Path of Perl. # File::Path provides "mkpath" and "rmtree". FileUtils.rm_r(@path) self end
root? is a predicate for root directories. I.e. it returns true if the path consists of consecutive slashes.
It doesn't access actual filesystem. So it may return false for some paths which points to roots such as /usr/...
# File lib/path/predicates.rb, line 19 def root? is_root?(@path) end
See File.setgid?.
# File lib/path/file_predicates.rb, line 91 def setgid? File.setgid?(@path) end
See File.setuid?.
# File lib/path/file_predicates.rb, line 86 def setuid? File.setuid?(@path) end
Returns the file size in bytes. See File.size.
# File lib/path/file.rb, line 77 def size File.size(@path) end
See File.size?.
# File lib/path/file_predicates.rb, line 96 def size? File.size?(@path) end
See File.socket?.
# File lib/path/file_predicates.rb, line 54 def socket? File.socket?(@path) end
split_names(path) -> prefix, [name, ...]
# File lib/path/implementation.rb, line 187 def split_names(path) names = [] while r = chop_basename(path) path, basename = r names.unshift basename if basename != '.' end return path, names end
Returns the stat of path as a +File::Stat+ object. See File.stat.
# File lib/path/file.rb, line 67 def stat File.stat(@path) end
See File.sticky?.
# File lib/path/file_predicates.rb, line 101 def sticky? File.sticky?(@path) end
See File.symlink?.
# File lib/path/file_predicates.rb, line 106 def symlink? File.symlink?(@path) end
See IO.sysopen.
# File lib/path/io.rb, line 41 def sysopen(*args) IO.sysopen(@path, *args) end
Returns the last bytes bytes of the file. If the file size is smaller than bytes, return the whole contents.
# File lib/path/io.rb, line 97 def tail(bytes) return read if size < bytes open { |f| f.seek(-bytes, IO::SEEK_END) f.read } end
JSON dumping.
# File lib/path/identity.rb, line 131 def to_json(*args) { 'json_class' => 'Path', 'data' => @path }.to_json(*args) end
Returns the path as a Symbol.
# File lib/path/identity.rb, line 109 def to_sym @path.to_sym end
Updates access and modification time or create an empty file.
# File lib/path/fileutils.rb, line 57 def touch if exist? now = Time.now File.utime(now, now, @path) else open('w') {} end self end
Truncates the file to length bytes. See File.truncate.
# File lib/path/file.rb, line 91 def truncate(length) File.truncate(@path, length) end
Removes a file using File.unlink. This is incompatible with Pathname#unlink, which can also remove directories. Use {rmdir} or {rm_r} for directories.
# File lib/path/file.rb, line 99 def unlink File.unlink @path end
Returns whether self is newer than all others. Non-existent files are older than any file. See FileUtils.uptodate?.
# File lib/path/fileutils.rb, line 106 def uptodate?(*others) FileUtils.uptodate?(@path, others) end
Updates the access and modification times. See File.utime.
# File lib/path/file.rb, line 105 def utime(atime, mtime) File.utime(atime, mtime, @path) end
# File lib/path/implementation.rb, line 161 def validate(path) raise ArgumentError, "path contains a null byte: #{path.inspect}" if path.include? "\00"" path.gsub!(File::ALT_SEPARATOR, '/') if File::ALT_SEPARATOR path = File.expand_path(path) if path.start_with? '~' path end
Removes the last extension of path.
Path('script.rb').without_extension # => #<Path script>
Path('archive.tar.gz').without_extension # => #<Path archive.tar>
# File lib/path/parts.rb, line 56 def without_extension Path.new @path[0..-extname.size-1] end
See File.world_readable?.
# File lib/path/file_predicates.rb, line 70 def world_readable? File.world_readable?(@path) end
See File.world_writable?.
# File lib/path/file_predicates.rb, line 117 def world_writable? File.world_writable?(@path) end
See File.writable?.
# File lib/path/file_predicates.rb, line 111 def writable? File.writable?(@path) end
See File.writable_real?.
# File lib/path/file_predicates.rb, line 128 def writable_real? File.writable_real?(@path) end
Writes contents to self. See IO.write or +IO#write+.
# File lib/path/io.rb, line 47 def write(contents, *open_args) IO.write(@path, contents, *open_args) end
YAML loading.
# File lib/path/identity.rb, line 119 def yaml_initialize(tag, ivars) @path = ivars['path'] init end
See File.zero?. empty? is not defined in File/FileTest, but is is clearer.
# File lib/path/file_predicates.rb, line 134 def zero? File.zero?(@path) end
Generated with the Darkfish Rdoc Generator 2.