Class: Path
- Inherits:
-
Object
- Object
- Path
- Defined in:
- lib/rubypath.rb,
lib/rubypath/mock.rb,
lib/rubypath/backend.rb,
lib/rubypath/version.rb,
lib/rubypath/identity.rb,
lib/rubypath/comparison.rb,
lib/rubypath/extensions.rb,
lib/rubypath/construction.rb,
lib/rubypath/io_operations.rb,
lib/rubypath/dir_operations.rb,
lib/rubypath/file_operations.rb,
lib/rubypath/file_predicates.rb,
lib/rubypath/path_operations.rb,
lib/rubypath/path_predicates.rb
Defined Under Namespace
Modules: VERSION Classes: Backend
Construction collapse
- EMPTY =
Empty path.
Path.new('')
Mocking / Virtual File System collapse
-
.mock(opts = {}) {|root, backend| ... } ⇒ Object
Configure current path backend.
Identity collapse
-
#inspect ⇒ String
Return a useful object string representation.
-
#path ⇒ String
(also: #to_path, #to_str, #to_s)
Return path as string.
Comparison collapse
-
#eql?(other) ⇒ Boolean
(also: #==)
Compare path to given object.
File Extensions collapse
-
#extension ⇒ String
(also: #ext)
Return last file extension.
-
#extensions ⇒ Array<String>
(also: #exts)
Return list of all file extensions.
-
#extname ⇒ String
Return last file extension include dot character.
-
#pure_name ⇒ String
Return the file name without any extensions.
-
#replace_extension(*args) ⇒ Path
Replace last extension with one or multiple new extensions.
-
#replace_extensions(*args) ⇒ Path
Replace file extensions with given new ones or by a given translation map.
Construction collapse
-
.like?(obj) ⇒ Boolean
Check if given object is like a path.
-
.like_path(obj) ⇒ String
Convert given object to path string using Path.like? rules.
-
.new(*args) ⇒ Object
Create new Path.
-
.separator ⇒ String
Return system file path separator.
-
.to_proc ⇒ Object
Allow class object to be used as a bock.
-
#initialize([[String, #to_path, #path, #to_s], ...]) ⇒ Path
constructor
Initialize new Path object.
IO Operations collapse
-
#read(*args) ⇒ String
Read file content from disk.
-
#write(content, *args) ⇒ Path
Write given content to file.
Directory Operations collapse
-
#entries(*args) ⇒ Array<Path>
Return list of entries in directory.
- #glob(pattern, flags = nil, &block) ⇒ Object
-
#mkdir(*args) ⇒ Path
Create directory.
-
#mkpath(*args) ⇒ Path
(also: #mkdir_p)
Create directory and all missing parent directories.
-
#rmtree(*args) ⇒ Path
(also: #rm_rf)
Removes file or directory.
-
#rmtree!(*args) ⇒ Path
(also: #rm_r)
Removes file or directory.
-
#safe_rmtree(*args) ⇒ Path
Removes file or directory.
-
#safe_rmtree!(*args) ⇒ Path
Removes file or directory.
File Operations collapse
-
.umask(mask = nil) ⇒ Object
(also: umask=)
Read or set process umask.
-
#atime ⇒ Time
Return file access time.
-
#atime=(time) ⇒ Object
Set last access time.
- #chmod(mode) ⇒ Object
-
#lookup(pattern, flags = nil) ⇒ Path
Search for a file in current directory or parent directories.
-
#mkfile(*args) ⇒ Path
Create a file at pointed location and all missing parent directories.
- #mode ⇒ Object
-
#mtime ⇒ Time
Return file modification time.
-
#mtime=(time) ⇒ Object
Set last modification time.
-
#name ⇒ String
(also: #basename)
Return base name without path.
-
#touch(*args) ⇒ Path
Create new file at pointed location or update modification time if file exists.
-
#unlink(*args) ⇒ Path
Removes file at current path.
File Predicates collapse
-
#directory? ⇒ Boolean
Check if path points to a directory.
-
#exists? ⇒ Boolean
(also: #exist?, #existent?)
Check if path points to an existing location.
-
#file? ⇒ Boolean
Check if path points to file.
Path Operations collapse
-
#ancestors ⇒ Array<Path>
Return an array of all ancestors.
-
#as_absolute ⇒ Path
Return given path as a absolute path by just prepending a leading slash.
-
#as_relative ⇒ Path
Return given path as a relative path by just striping leading slashes.
-
#ascend {|path| ... } ⇒ Path
(also: #each_ancestors)
Yield given block for path and each ancestor.
-
#cleanpath ⇒ Path
Return cleaned path with all dot components removed.
-
#components ⇒ Array<String>
Return an array with all path components.
-
#dirname ⇒ Path
(also: #parent)
Return path to parent directory.
-
#each_component(opts = {}, &block) ⇒ Object
Iterate over all path components.
-
#expand(*args) ⇒ Path
(also: #expand_path, #absolute, #absolute_path)
Converts a pathname to an absolute pathname.
-
#initialize([[Path, String, #to_path, #path, #to_s], ...]) ⇒ Path
Join path with given arguments.
-
#only_filename? ⇒ Boolean
Check if path consists of only a filename.
-
#relative_from(base) ⇒ Path
(also: #relative_path_from)
Return a relative path from the given base path to the receiver path.
Path Predicates collapse
-
#absolute? ⇒ Boolean
Check if path is an absolute path.
-
#dotfile? ⇒ Boolean
Check if file or directory is a dot file.
-
#mountpoint?(*args) ⇒ Boolean
True if path is a mountpoint, false otherwise.
-
#relative? ⇒ Boolean
Check if path is a relative path.
Class Method Summary collapse
-
.getwd ⇒ Path
Returns the current working directory.
- .glob(pattern, flags = nil) ⇒ Object
Constructor Details
#initialize([[String, #to_path, #path, #to_s], ...]) ⇒ Path
Initialize new Path object.
Given arguments will be converted to String using ‘#to_path`, `#path` or `#to_s` in this order if they return a String object.
93 94 95 96 97 98 99 100 101 102 |
# File 'lib/rubypath/construction.rb', line 93 def initialize(*args) parts = args.flatten @path = if parts.size > 1 ::File.join(*parts.map{|p| Path.like_path p }) elsif parts.size == 1 Path.like_path(parts.first).dup else '' end end |
Class Method Details
.getwd ⇒ Path
Returns the current working directory.
9 10 11 |
# File 'lib/rubypath/dir_operations.rb', line 9 def getwd new Backend.instance.getwd end |
.glob(pattern, flags = nil) ⇒ Object
13 14 15 16 17 18 19 20 21 |
# File 'lib/rubypath/dir_operations.rb', line 13 def glob(pattern, flags = nil) flags = default_glob_flags(flags) if block_given? Backend.instance.glob(pattern, flags) {|path| yield Path path } else Backend.instance.glob(pattern, flags).map(&Path) end end |
.like?(obj) ⇒ Boolean
33 34 35 36 37 38 39 |
# File 'lib/rubypath/construction.rb', line 33 def like?(obj) return true if obj.is_a?(self) return true if obj.is_a?(String) return true if obj.respond_to?(:to_path) && obj.to_path.is_a?(String) return true if obj.respond_to?(:path) && obj.path.is_a?(String) false end |
.like_path(obj) ⇒ String
Should not be used directly.
Convert given object to path string using like? rules.
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/rubypath/construction.rb', line 49 def like_path(obj) case obj when String return obj else [:to_path, :path, :to_str, :to_s].each do |mth| if obj.respond_to?(mth) && obj.send(mth).is_a?(String) return obj.send(mth) end end end raise ArgumentError.new \ "Argument #{obj.inspect} cannot be converted to path string." end |
.mock(opts = {}) {|root, backend| ... } ⇒ Object
Configure current path backend. Can be used to configure specified test scenario. If no virtual or scoped path backend is set the default one will be used.
Do not forget to use mock file system in your specs: See more Path::Backend.mock.
around do |example|
Path::Backend.mock &example
end
Note: Not all operations are supported.
37 38 39 40 |
# File 'lib/rubypath/mock.rb', line 37 def mock(opts = {}) yield Path('/'), Backend.instance.backend if block_given? nil end |
.new(*args) ⇒ Object
14 15 16 17 18 19 |
# File 'lib/rubypath/construction.rb', line 14 def new(*args) args.flatten! return Path::EMPTY if args.empty? return args.first if args.size == 1 && args.first.is_a?(self) super end |
.separator ⇒ String
Return system file path separator.
70 71 72 |
# File 'lib/rubypath/construction.rb', line 70 def separator ::File::SEPARATOR end |
.to_proc ⇒ Object
Allow class object to be used as a bock.
79 80 81 |
# File 'lib/rubypath/construction.rb', line 79 def to_proc proc {|*args| Path.new(*args) } end |
.umask ⇒ Integer .umask(mask) ⇒ Object Also known as: umask=
Read or set process umask.
183 184 185 186 187 188 189 |
# File 'lib/rubypath/file_operations.rb', line 183 def umask(mask = nil) if mask invoke_backend :set_umask, mask else invoke_backend :get_umask end end |
Instance Method Details
#absolute? ⇒ Boolean
Check if path is an absolute path.
An absolute path is a path with a leading slash.
11 12 13 |
# File 'lib/rubypath/path_predicates.rb', line 11 def absolute? internal_path[0] == '/' end |
#ancestors ⇒ Array<Path>
Return an array of all ancestors.
218 219 220 |
# File 'lib/rubypath/path_operations.rb', line 218 def ancestors each_ancestors.to_a end |
#as_absolute ⇒ Path
Return given path as a absolute path by just prepending a leading slash.
246 247 248 249 250 251 252 |
# File 'lib/rubypath/path_operations.rb', line 246 def as_absolute if internal_path[0] != '/' Path "/#{internal_path}" else self end end |
#as_relative ⇒ Path
Return given path as a relative path by just striping leading slashes.
230 231 232 233 234 235 236 |
# File 'lib/rubypath/path_operations.rb', line 230 def as_relative if (rel_path = internal_path.gsub(/^\/+/, '')) != internal_path Path rel_path else self end end |
#ascend {|path| ... } ⇒ Path Also known as: each_ancestors
Yield given block for path and each ancestor.
196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/rubypath/path_operations.rb', line 196 def ascend return to_enum(:ascend) unless block_given? path = self loop do yield path break unless (path = path.parent) end self end |
#atime ⇒ Time
Return file access time.
147 148 149 |
# File 'lib/rubypath/file_operations.rb', line 147 def atime invoke_backend :atime end |
#atime=(time) ⇒ Object
Set last access time.
155 156 157 |
# File 'lib/rubypath/file_operations.rb', line 155 def atime=(time) invoke_backend :atime=, internal_path, time end |
#chmod(mode) ⇒ Object
163 164 165 |
# File 'lib/rubypath/file_operations.rb', line 163 def chmod(mode) invoke_backend :chmod, internal_path, mode end |
#cleanpath ⇒ Path
Return cleaned path with all dot components removed.
No file system will accessed and not symlinks will be resolved.
297 298 299 300 301 302 303 304 |
# File 'lib/rubypath/path_operations.rb', line 297 def cleanpath path = Pathname.new(self).cleanpath if path == internal_path self else Path path end end |
#components ⇒ Array<String>
Return an array with all path components.
85 86 87 |
# File 'lib/rubypath/path_operations.rb', line 85 def components each_component.to_a end |
#directory? ⇒ Boolean
Check if path points to a directory.
29 30 31 |
# File 'lib/rubypath/file_predicates.rb', line 29 def directory? invoke_backend :directory? end |
#dirname ⇒ Path Also known as: parent
Return path to parent directory. If path is already an absolute or relative root nil will be returned.
165 166 167 168 169 170 |
# File 'lib/rubypath/path_operations.rb', line 165 def dirname return nil if %w(. /).include? internal_path dir = ::File.dirname internal_path dir.empty? ? nil : self.class.new(dir) end |
#dotfile? ⇒ Boolean
Check if file or directory is a dot file.
58 59 60 |
# File 'lib/rubypath/path_predicates.rb', line 58 def dotfile? name[0] == '.' end |
#each_component ⇒ Enumerator #each_component(&block) ⇒ self
Iterate over all path components.
60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/rubypath/path_operations.rb', line 60 def each_component(opts = {}, &block) rv = if opts[:empty] # split eats leading slashes ary = path.split(Path.separator) # so add an empty string if path ends with slash ary << '' if path[-1] == Path.separator ary.each(&block) else Pathname(path).each_filename(&block) end block ? self : rv end |
#entries(*args) ⇒ Array<Path>
Return list of entries in directory. That includes special directories (‘.`, `..`).
Given arguments will be joined before children are listed for directory.
76 77 78 |
# File 'lib/rubypath/dir_operations.rb', line 76 def entries(*args) invoke_backend(:entries, internal_path).map(&Path) end |
#eql?(other) ⇒ Boolean Also known as: ==
Compare path to given object. If object is a string, Path or #like? they will be compared using the string paths. Otherwise they are assumed as not equal.
11 12 13 14 15 16 17 |
# File 'lib/rubypath/comparison.rb', line 11 def eql?(other) if other.is_a?(Path) cleanpath.internal_path == other.cleanpath.internal_path else Path.new(other).eql?(self) if Path.like?(other) end end |
#exists? ⇒ Boolean Also known as: exist?, existent?
Check if path points to an existing location.
18 19 20 |
# File 'lib/rubypath/file_predicates.rb', line 18 def exists? invoke_backend :exists? end |
#expand(*args) ⇒ Path Also known as: expand_path, absolute, absolute_path
Converts a pathname to an absolute pathname. Given arguments will be joined to current path before expanding path. Relative paths are referenced from the current working directory of the process unless the ‘:base` option is set, which will be used as the starting point.
The given pathname may start with a “~”, which expands to the process owner’s home directory (the environment variable HOME must be set correctly). “~user” expands to the named user’s home directory.
117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/rubypath/path_operations.rb', line 117 def (*args) opts = args.last.is_a?(Hash) ? args.pop : {} with_path(*args) do |path| base = Path.like_path(opts[:base] || Backend.instance.getwd) = Backend.instance.(path, base) if != internal_path Path else self end end end |
#extension ⇒ String Also known as: ext
Return last file extension.
29 30 31 |
# File 'lib/rubypath/extensions.rb', line 29 def extension extensions.last end |
#extensions ⇒ Array<String> Also known as: exts
Return list of all file extensions.
12 13 14 15 16 17 18 |
# File 'lib/rubypath/extensions.rb', line 12 def extensions if dotfile? name.split('.')[2..-1] else name.split('.')[1..-1] end end |
#extname ⇒ String
Return last file extension include dot character.
39 40 41 |
# File 'lib/rubypath/extensions.rb', line 39 def extname ::File.extname name end |
#file? ⇒ Boolean
Check if path points to file.
9 10 11 |
# File 'lib/rubypath/file_predicates.rb', line 9 def file? invoke_backend :file? end |
#glob(pattern, flags = nil, &block) ⇒ Object
81 82 83 |
# File 'lib/rubypath/dir_operations.rb', line 81 def glob(pattern, flags = nil, &block) Path.glob(::File.join(escaped_glob_path, pattern), flags, &block) end |
#inspect ⇒ String
Return a useful object string representation.
18 19 20 |
# File 'lib/rubypath/identity.rb', line 18 def inspect "<#{self.class.name}:#{internal_path}>" end |
#initialize([[Path, String, #to_path, #path, #to_s], ...]) ⇒ Path
Join path with given arguments.
15 16 17 18 19 20 21 22 23 24 25 26 |
# File 'lib/rubypath/path_operations.rb', line 15 def join(*args) parts = args.flatten case parts.size when 0 self when 1 join = Path parts.shift join.absolute? ? join : Path(::File.join(path, join.path)) else join(parts.shift).join(*parts) end end |
#lookup(pattern, flags = nil) ⇒ Path
Search for a file in current directory or parent directories.
Given search pattern can either be a regular expression or a shell glob expression.
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/rubypath/file_operations.rb', line 108 def lookup(pattern, flags = nil) flags = self.class.default_glob_flags(flags) .ascend do |path| case pattern when String path.entries.each do |c| return path.join(c) if ::File.fnmatch?(pattern, c.name, flags) end when Regexp path.entries.each do |c| return path.join(c) if pattern =~ c.name end end end nil end |
#mkdir(*args) ⇒ Path
Create directory.
Given arguments will be joined with current path before directory is created.
45 46 47 48 49 50 |
# File 'lib/rubypath/dir_operations.rb', line 45 def mkdir(*args) with_path(*args) do |path| Backend.instance.mkdir path Path path end end |
#mkfile(*args) ⇒ Path
Create a file at pointed location and all missing parent directories.
Given arguments will be joined with current path before directories and file is created.
If file already exists nothing will be done.
72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/rubypath/file_operations.rb', line 72 def mkfile(*args) with_path(*args) do |path| if !path.exists? && path.parent && !path.parent.exists? path.parent.mkpath end if path.exists? raise Errno::ENOENT.new path.to_s unless path.file? else path.touch end end end |
#mkpath(*args) ⇒ Path Also known as: mkdir_p
Create directory and all missing parent directories.
Given arguments will be joined with current path before directories are created.
61 62 63 64 65 66 |
# File 'lib/rubypath/dir_operations.rb', line 61 def mkpath(*args) with_path(*args) do |path| Backend.instance.mkpath path Path path end end |
#mode ⇒ Object
159 160 161 |
# File 'lib/rubypath/file_operations.rb', line 159 def mode invoke_backend :mode end |
#mountpoint?([Path, String], ...) ⇒ Boolean #mountpoint? ⇒ Boolean
Returns True if path is a mountpoint, false otherwise.
44 45 46 47 48 |
# File 'lib/rubypath/path_predicates.rb', line 44 def mountpoint?(*args) with_path(*args) do |path| Backend.instance.mountpoint? path end end |
#mtime ⇒ Time
Return file modification time.
131 132 133 |
# File 'lib/rubypath/file_operations.rb', line 131 def mtime invoke_backend :mtime end |
#mtime=(time) ⇒ Object
Set last modification time.
139 140 141 |
# File 'lib/rubypath/file_operations.rb', line 139 def mtime=(time) invoke_backend :mtime=, internal_path, time end |
#name ⇒ String Also known as: basename
Return base name without path.
8 9 10 |
# File 'lib/rubypath/file_operations.rb', line 8 def name ::File.basename internal_path end |
#only_filename? ⇒ Boolean
Check if path consists of only a filename.
143 144 145 |
# File 'lib/rubypath/path_operations.rb', line 143 def only_filename? internal_path.index(Path.separator).nil? end |
#path ⇒ String Also known as: to_path, to_str, to_s
Return path as string. String will be duped before it gets returned and cannot be used to modify the path object.
8 9 10 |
# File 'lib/rubypath/identity.rb', line 8 def path internal_path.dup end |
#pure_name ⇒ String
Return the file name without any extensions.
55 56 57 58 59 60 61 |
# File 'lib/rubypath/extensions.rb', line 55 def pure_name if dotfile? name.split('.', 3)[0..1].join('.') else name.split('.', 2)[0] end end |
#read([..]) ⇒ String #read(length, [..]) ⇒ String #read(length, offset, [..]) ⇒ String
Read file content from disk.
79 80 81 |
# File 'lib/rubypath/io_operations.rb', line 79 def read(*args) invoke_backend :read, self, *args end |
#relative? ⇒ Boolean
Check if path is a relative path.
A relative path does not start with a slash.
22 23 24 |
# File 'lib/rubypath/path_predicates.rb', line 22 def relative? !absolute? end |
#relative_from(base) ⇒ Path Also known as: relative_path_from
Return a relative path from the given base path to the receiver path.
Both paths need to be either absolute or relative otherwise an error will be raised. The file system will not be accessed and no symlinks are assumed.
268 269 270 271 272 273 274 275 276 277 278 279 280 |
# File 'lib/rubypath/path_operations.rb', line 268 def relative_from(base) base, path = Path(base).cleanpath, cleanpath if (base.relative? && path.absolute?) || (base.absolute? && path.relative?) raise ArgumentError.new \ "Different prefix: #{base.inspect} and #{path.inspect}" end base, path = base.components, path.components base.shift && path.shift while base.first == path.first Path(*((['..'] * base.size) + path)) end |
#replace_extension(*args) ⇒ Path
Replace last extension with one or multiple new extensions.
149 150 151 152 153 154 155 |
# File 'lib/rubypath/extensions.rb', line 149 def replace_extension(*args) extensions = self.extensions extensions.pop extensions += args.flatten replace_extensions extensions end |
#replace_extensions(exts) ⇒ Path #replace_extensions(ext, [ext, [..]]) ⇒ Path #replace_extensions(map) ⇒ Path
Replace file extensions with given new ones or by a given translation map.
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 |
# File 'lib/rubypath/extensions.rb', line 109 def replace_extensions(*args) args.flatten! extensions = self.extensions if (replace = (args.last.is_a?(Hash) ? args.pop : nil)) if args.empty? extensions.map! do |ext| replace[ext] ? replace[ext].to_s : ext end else raise ArgumentError.new 'Cannot replace extensions with array ' \ 'and hash at the same time.' end else extensions = args.map(&:to_s) end if extensions == self.extensions self else if only_filename? Path "#{pure_name}.#{extensions.join('.')}" else dirname.join "#{pure_name}.#{extensions.join('.')}" end end end |
#rmtree(*args) ⇒ Path Also known as: rm_rf
Removes file or directory. If it’s a directory it will be removed recursively.
WARNING: This method causes local vulnerability if one of parent directories or removing directory tree are world writable (including ‘/tmp`, whose permission is 1777), and the current process has strong privilege such as Unix super user (root), and the system has symbolic link. For secure removing see #safe_rmtree.
96 97 98 99 100 101 |
# File 'lib/rubypath/dir_operations.rb', line 96 def rmtree(*args) with_path(*args) do |path| invoke_backend :rmtree, internal_path Path path end end |
#rmtree!(*args) ⇒ Path Also known as: rm_r
Removes file or directory. If it’s a directory it will be removed recursively.
This method behaves exactly like #rmtree but will raise exceptions e.g. when file does not exist.
132 133 134 135 136 137 |
# File 'lib/rubypath/dir_operations.rb', line 132 def rmtree!(*args) with_path(*args) do |path| invoke_backend :rmtree!, internal_path Path path end end |
#safe_rmtree(*args) ⇒ Path
Removes file or directory. If it’s a directory it will be removed recursively.
This method uses #FileUtils#remove_entry_secure to avoid TOCTTOU (time-of-check-to-time-of-use) local security vulnerability of #rmtree. #rmtree causes security hole when:
-
Parent directory is world writable (including ‘/tmp`).
-
Removing directory tree includes world writable directory.
-
The system has symbolic link.
117 118 119 120 121 122 |
# File 'lib/rubypath/dir_operations.rb', line 117 def safe_rmtree(*args) with_path(*args) do |path| invoke_backend :safe_rmtree, internal_path Path path end end |
#safe_rmtree!(*args) ⇒ Path
Removes file or directory. If it’s a directory it will be removed recursively.
This method behaves exactly like #safe_rmtree but will raise exceptions e.g. when file does not exist.
148 149 150 151 152 153 |
# File 'lib/rubypath/dir_operations.rb', line 148 def safe_rmtree!(*args) with_path(*args) do |path| invoke_backend :safe_rmtree!, internal_path Path path end end |
#touch(*args) ⇒ Path
Create new file at pointed location or update modification time if file exists.
26 27 28 29 30 31 |
# File 'lib/rubypath/file_operations.rb', line 26 def touch(*args) with_path(*args) do |path| invoke_backend :touch, path Path path end end |