Class: Pathname2

Inherits:
String show all
Extended by:
FFI::Library, Facade
Defined in:
lib/pathname2.rb

Defined Under Namespace

Classes: Error

Constant Summary collapse

VERSION =

The version of the pathname2 library

'2.0.0'.freeze
MAXPATH =

The maximum length of a path

1024

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from String

#to_path, #wincode

Constructor Details

#initialize(path) ⇒ Pathname2

Creates and returns a new Pathname2 object.

On platforms that define File::ALT_SEPARATOR, all forward slashes are replaced with the value of File::ALT_SEPARATOR. On MS Windows, for example, all forward slashes are replaced with backslashes.

File URL's will be converted to Pathname2 objects, e.g. the file URL "file:///C:/Documents%20and%20Settings" will become 'C:Documents and Settings'.

Examples:

Pathname2.new("/foo/bar/baz")
Pathname2.new("foo")
Pathname2.new("file:///foo/bar/baz")
Pathname2.new("C:\\Documents and Settings\\snoopy")


131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/pathname2.rb', line 131

def initialize(path)
  if path.length > MAXPATH
    msg = 'string too long.  maximum string length is ' + MAXPATH.to_s
    raise ArgumentError, msg
  end

  @sep = File::ALT_SEPARATOR || File::SEPARATOR
  @win = File::ALT_SEPARATOR

  # Handle File URL's. The separate approach for Windows is necessary
  # because Ruby's URI class does not (currently) parse absolute file URL's
  # properly when they include a drive letter.
  if @win
    wpath = path.wincode

    if PathIsURLW(wpath)
      buf = FFI::MemoryPointer.new(:char, MAXPATH)
      len = FFI::MemoryPointer.new(:ulong)
      len.write_ulong(buf.size)

      if PathCreateFromUrlW(wpath, buf, len, 0) == 0
        path = buf.read_string(path.size * 2).tr(0.chr, '')
      else
        raise Error, "invalid file url: #{path}"
      end
    end
  else
    if path.index('file:///', 0)
      require 'addressable'
      path = Addressable::URI.unescape(path)[7..-1]
    end
  end

  # Convert forward slashes to backslashes on Windows
  path = path.tr(File::SEPARATOR, File::ALT_SEPARATOR) if @win

  super(path)
end

Class Method Details

.pwdObject Also known as: getwd

Returns the expanded path of the current working directory.

Synonym for Pathname2.new(Dir.pwd).



107
108
109
# File 'lib/pathname2.rb', line 107

def self.pwd
  new(Dir.pwd)
end

Instance Method Details

#+(string) ⇒ Object Also known as: /

Adds two Pathname2 objects together, or a Pathname2 and a String. It also automatically cleans the Pathname2.

Adding a root path to an existing path merely replaces the current path. Adding '.' to an existing path does nothing.

Example:

path1 = '/foo/bar'
path2 = '../baz'
path1 + path2 # '/foo/baz'


681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
# File 'lib/pathname2.rb', line 681

def +(string)
  unless string.is_a?(Pathname2)
    string = self.class.new(string)
  end

  # Any path plus "." is the same directory
  return self if string == '.'
  return string if self == '.'

  # Use the builtin PathAppend() function if on Windows - much easier
  if @win
    path = FFI::MemoryPointer.new(:char, MAXPATH)
    path.write_string(dup.wincode)
    more = FFI::MemoryPointer.from_string(string.wincode)

    PathAppendW(path, more)

    path = path.read_string(path.size).split("\000\000").first.delete(0.chr)

    return self.class.new(path) # PathAppend cleans automatically
  end

  # If the string is an absolute directory, return it
  return string if string.absolute?

  array = to_a + string.to_a
  new_string = array.join(@sep)

  unless relative? || @win
    temp = @sep + new_string # Add root path back if needed
    new_string.replace(temp)
  end

  self.class.new(new_string).clean
end

#<=>(string) ⇒ Object

Compares two Pathname2 objects. Note that Pathname2 objects may only be compared against other Pathname2 objects, not strings, otherwise nil is returned.

Example:

path1 = Pathname2.new('/usr/local')
path2 = Pathname2.new('/usr/local')
path3 = Pathname2.new('/usr/local/bin')

path1 <=> path2 # => 0
path1 <=> path3 # => -1


586
587
588
589
# File 'lib/pathname2.rb', line 586

def <=>(string)
  return nil unless string.is_a?(Pathname2)
  super
end

#[](index, length = nil) ⇒ Object

Returns the path component at index, up to length components, joined by the path separator. If the index is a Range, then that is used instead and the length is ignored.

Keep in mind that on MS Windows the drive letter is the first element.

Examples:

path = Pathname2.new('/home/john/source/ruby')
path[0]    # => 'home'
path[1]    # => 'john'
path[0, 3] # => '/home/john/source'
path[0..1] # => '/home/john'

path = Pathname2.new('C:/Documents and Settings/John/Source/Ruby')
path[0]    # => 'C:\'
path[1]    # => 'Documents and Settings'
path[0, 3] # => 'C:\Documents and Settings\John'
path[0..1] # => 'C:\Documents and Settings'


377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
# File 'lib/pathname2.rb', line 377

def [](index, length=nil)
  if index.is_a?(Numeric)
    if length
      path = File.join(to_a[index, length])
    else
      path = to_a[index]
    end
  elsif index.is_a?(Range)
    if length
      warn 'Length argument ignored'
    end
    path = File.join(to_a[index])
  else
    raise TypeError, 'Only Numerics and Ranges allowed as first argument'
  end

  if path && @win
    path = path.tr(File::SEPARATOR, File::ALT_SEPARATOR)
  end

  path
end

#absolute?Boolean

Returns whether or not the path is an absolute path.

Example:

Pathname2.new('/usr/bin').absolute? # => true
Pathname2.new('usr').absolute?      # => false

Returns:

  • (Boolean)


726
727
728
# File 'lib/pathname2.rb', line 726

def absolute?
  !relative?
end

#ascendObject

Yields the path, minus one component on each iteration, as a new Pathname2 object, ending with the root path.

Example:

path = Pathname2.new('/usr/local/bin')

path.ascend{ |name|
  puts name
}

First iteration  => '/usr/local/bin'
Second iteration => '/usr/local'
Third iteration  => '/usr'
Fourth iteration => '/'


458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
# File 'lib/pathname2.rb', line 458

def ascend
  if root?
    yield root
    return
  end

  n = to_a.length

  while n > 0
    path = to_a[0..n-1].join(@sep)
    if absolute?
      if @win && unc?
        path = "\\\\" << path
      end
      unless @win
        path = root << path
      end
    end

    path = self.class.new(path)
    yield path

    if @win && unc?
      break if path.root?
    end

    n -= 1
  end

  # Yield the root directory if an absolute path (and not Windows)
  unless @win
    yield root if absolute?
  end
end

#basename(*args) ⇒ Object

File.basename



992
993
994
# File 'lib/pathname2.rb', line 992

def basename(*args)
  self.class.new(File.basename(self, *args))
end

#cd(*args, &block) ⇒ Object

FileUtils.cd



1007
1008
1009
# File 'lib/pathname2.rb', line 1007

def cd(*args, &block)
  FileUtils.cd(self, *args, &block)
end

#chdir(&block) ⇒ Object

Dir.chdir



910
911
912
# File 'lib/pathname2.rb', line 910

def chdir(&block)
  Dir.chdir(self, &block)
end

#children(with_directory = true) ⇒ Object

Returns the children of the directory, files and subdirectories, as an array of Pathname2 objects. If you set with_directory to false, then the returned pathnames will contain the filename only.

Note that the result never contain the entries '.' and '..' in the the directory because they are not children. Also note that this method is not recursive.

Example:

path = Pathname2.new('/usr/bin') path.children # => ['/usr/bin/ruby', '/usr/bin/perl', ...] path.children(false) # => ['ruby', 'perl', ...]



213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/pathname2.rb', line 213

def children(with_directory = true)
  with_directory = false if self == '.'
  result = []
  Dir.foreach(self) do |file|
    next if file == '.' || file == '..'
    if with_directory
      result << self.class.new(File.join(self, file))
    else
      result << self.class.new(file)
    end
  end
  result
end

#chmod(mode) ⇒ Object

File.chmod



932
933
934
# File 'lib/pathname2.rb', line 932

def chmod(mode)
  File.chmod(mode, self)
end

#chown(owner, group) ⇒ Object

File.chown



942
943
944
# File 'lib/pathname2.rb', line 942

def chown(owner, group)
  File.chown(owner, group, self)
end

#cleanObject Also known as: cleanpath

Removes unnecessary '.' paths and ellides '..' paths appropriately. This method is non-destructive.

Example:

path = Pathname2.new('/usr/./local/../bin')
path.clean # => '/usr/bin'


753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
# File 'lib/pathname2.rb', line 753

def clean
  return self if empty?

  if @win
    ptr = FFI::MemoryPointer.new(:char, MAXPATH)
    if PathCanonicalizeW(ptr, wincode)
      return self.class.new(ptr.read_string(ptr.size).delete(0.chr))
    else
      return self
    end
  end

  final = []

  to_a.each do |element|
    next if element == '.'
    final.push(element)
    if element == '..' && self != '..'
      2.times{ final.pop }
    end
  end

  final = final.join(@sep)
  final = root._plus_(final) if root != '.'
  final = '.' if final.empty?

  self.class.new(final)
end

#clean!Object Also known as: cleanpath!

Identical to Pathname2#clean, except that it modifies the receiver in place.



787
788
789
# File 'lib/pathname2.rb', line 787

def clean!
  replace(clean)
end

#compare_file(file) ⇒ Object

FileUtils.compare_file



1086
1087
1088
# File 'lib/pathname2.rb', line 1086

def compare_file(file)
  FileUtils.compare_file(self, file)
end

#copy_entry(*args) ⇒ Object

FileUtils.copy_entry



1111
1112
1113
# File 'lib/pathname2.rb', line 1111

def copy_entry(*args)
  FileUtils.copy_entry(self, *args)
end

#copy_file(*args) ⇒ Object

FileUtils.copy_file



1096
1097
1098
# File 'lib/pathname2.rb', line 1096

def copy_file(*args)
  FileUtils.copy_file(self, *args)
end

#cp(*args) ⇒ Object

FileUtils.cp



1034
1035
1036
# File 'lib/pathname2.rb', line 1034

def cp(*args)
  FileUtils.cp(self, *args)
end

#cp_r(*args) ⇒ Object

FileUtils.cp_r



1039
1040
1041
# File 'lib/pathname2.rb', line 1039

def cp_r(*args)
  FileUtils.cp_r(self, *args)
end

#descendObject

Yields each component of the path, concatenating the next component on each iteration as a new Pathname2 object, starting with the root path.

Example:

path = Pathname2.new('/usr/local/bin')

path.descend{ |name|
  puts name
}

First iteration  => '/'
Second iteration => '/usr'
Third iteration  => '/usr/local'
Fourth iteration => '/usr/local/bin'


416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
# File 'lib/pathname2.rb', line 416

def descend
  if root?
    yield root
    return
  end

  if @win
    path = unc? ? "#{root}\\" : ''
  else
    path = absolute? ? root : ''
  end

  # Yield the root directory if an absolute path (and not Windows)
  unless @win && !unc?
    yield root if absolute?
  end

  each do |element|
    if @win && unc?
      next if root.to_a.include?(element)
    end
    path << element << @sep
    yield self.class.new(path.chop)
  end
end

#dirname(level = 1) ⇒ Object

Similar to File.dirname, but this method allows you to specify the number of levels up you wish to refer to.

The default level is 1, i.e. it works the same as File.dirname. A level of 0 will return the original path. A level equal to or greater than the number of path elements will return the root path.

A number less than 0 will raise an ArgumentError.

Example:

path = Pathname2.new('/usr/local/bin/ruby')

puts path.dirname    # => /usr/local/bin
puts path.dirname(2) # => /usr/local
puts path.dirname(3) # => /usr
puts path.dirname(9) # => /

Raises:

  • (ArgumentError)


811
812
813
814
815
816
817
# File 'lib/pathname2.rb', line 811

def dirname(level = 1)
  raise ArgumentError if level < 0
  local_path = dup

  level.times{ local_path = File.dirname(local_path) }
  self.class.new(local_path)
end

#drive_numberObject

MS Windows only

Returns the drive number that corresponds to the root, or nil if not applicable.

Example:

Pathname2.new("C:\\foo").drive_number # => 2


564
565
566
567
568
569
570
571
# File 'lib/pathname2.rb', line 564

def drive_number
  unless @win
    raise NotImplementedError, 'not supported on this platform'
  end

  num = PathGetDriveNumberW(wincode)
  num >= 0 ? num : nil
end

#eachObject

Yields each component of the path name to a block.

Example:

Pathname2.new('/usr/local/bin').each{ |element|
  puts "Element: #{element}"
}

Yields 'usr', 'local', and 'bin', in turn


353
354
355
# File 'lib/pathname2.rb', line 353

def each
  to_a.each{ |element| yield element }
end

#entriesObject

Dir.entries



915
916
917
# File 'lib/pathname2.rb', line 915

def entries
  Dir.entries(self).map{ |file| self.class.new(file) }
end

#expand_path(*args) ⇒ Object

File.expand_path



997
998
999
# File 'lib/pathname2.rb', line 997

def expand_path(*args)
  self.class.new(File.expand_path(self, *args))
end

#findObject

Pathname2#find is an iterator to traverse a directory tree in a depth first manner. It yields a Pathname2 for each file under the directory passed to Pathname2.new.

Since it is implemented by the Find module, Find.prune can be used to control the traverse.

If self is ".", yielded pathnames begin with a filename in the current current directory, not ".".



860
861
862
863
864
865
866
867
# File 'lib/pathname2.rb', line 860

def find
  require 'find'
  if self == '.'
    Find.find(self){ |f| yield self.class.new(f.sub(%r{\A\./}, '')) }
  else
    Find.find(self){ |f| yield self.class.new(f) }
  end
end

#fnmatch(pattern, *args) ⇒ Object

File.fnmatch



952
953
954
# File 'lib/pathname2.rb', line 952

def fnmatch(pattern, *args)
  File.fnmatch(pattern, self, *args)
end

#fnmatch?(pattern, *args) ⇒ Boolean

File.fnmatch?

Returns:

  • (Boolean)


957
958
959
# File 'lib/pathname2.rb', line 957

def fnmatch?(pattern, *args)
  File.fnmatch?(pattern, self, *args)
end

#foreach(*args, &block) ⇒ Object

IO.foreach



872
873
874
# File 'lib/pathname2.rb', line 872

def foreach(*args, &block)
  File.foreach(self, *args, &block)
end

#glob(*args) ⇒ Object

Dir.glob

:no-doc: This differs from Tanaka's implementation in that it does a temporary chdir to the path in question, then performs the glob.



899
900
901
902
903
904
905
906
907
# File 'lib/pathname2.rb', line 899

def glob(*args)
  Dir.chdir(self) do
    if block_given?
      Dir.glob(*args){ |file| yield self.class.new(file) }
    else
      Dir.glob(*args).map{ |file| self.class.new(file) }
    end
  end
end

#install(*args) ⇒ Object

FileUtils.install



1076
1077
1078
# File 'lib/pathname2.rb', line 1076

def install(*args)
  FileUtils.install(self, *args)
end

#join(*args) ⇒ Object

Joins the given pathnames onto self to create a new Pathname2 object.

path = Pathname2.new("C:/Users") path = path.join("foo", "Downloads") # => C:/Users/foo/Downloads



824
825
826
827
828
829
830
831
832
833
834
835
836
837
# File 'lib/pathname2.rb', line 824

def join(*args)
  args.unshift self
  result = args.pop
  result = self.class.new(result) unless result === self.class
  return result if result.absolute?

  args.reverse_each do |path|
    path = self.class.new(path) unless path === self.class
    result = path + result
    break if result.absolute?
  end

  result
end

#lchmod(mode) ⇒ Object

File.lchmod



937
938
939
# File 'lib/pathname2.rb', line 937

def lchmod(mode)
  File.lchmod(mode, self)
end

#lchown(owner, group) ⇒ Object

File.lchown



947
948
949
# File 'lib/pathname2.rb', line 947

def lchown(owner, group)
  File.lchown(owner, group, self)
end

File.link



962
963
964
# File 'lib/pathname2.rb', line 962

def link(old)
  File.link(old, self)
end

#ln(*args) ⇒ Object

FileUtils.ln



1019
1020
1021
# File 'lib/pathname2.rb', line 1019

def ln(*args)
  FileUtils.ln(self, *args)
end

#ln_s(*args) ⇒ Object

FileUtils.ln_s



1024
1025
1026
# File 'lib/pathname2.rb', line 1024

def ln_s(*args)
  FileUtils.ln_s(self, *args)
end

#ln_sf(*args) ⇒ Object

FileUtils.ln_sf



1029
1030
1031
# File 'lib/pathname2.rb', line 1029

def ln_sf(*args)
  FileUtils.ln_sf(self, *args)
end

#long_pathObject

Windows only

Returns the long path for a long path name.

Example:

path = Pathname2.new('C:\Progra~1\Java')
path.long_path # => C:\Program Files\Java.

Raises:

  • (NotImplementedError)


287
288
289
290
291
292
293
294
295
296
297
298
# File 'lib/pathname2.rb', line 287

def long_path
  raise NotImplementedError, 'not supported on this platform' unless @win

  buf = FFI::MemoryPointer.new(:char, MAXPATH)
  wpath = wincode

  size = GetLongPathNameW(wpath, buf, buf.size)

  raise SystemCallError.new('GetShortPathName', FFI.errno) if size == 0

  self.class.new(buf.read_bytes(size * 2).delete(0.chr))
end

#mkdir(*args) ⇒ Object

Dir.mkdir



920
921
922
# File 'lib/pathname2.rb', line 920

def mkdir(*args)
  Dir.mkdir(self, *args)
end

#mkdir_p(*args) ⇒ Object Also known as: mkpath

FileUtils.mkdir_p



1012
1013
1014
# File 'lib/pathname2.rb', line 1012

def mkdir_p(*args)
  FileUtils.mkdir_p(self, *args)
end

#mv(*args) ⇒ Object

FileUtils.mv



1044
1045
1046
# File 'lib/pathname2.rb', line 1044

def mv(*args)
  FileUtils.mv(self, *args)
end

#open(*args, &block) ⇒ Object

File.open



967
968
969
# File 'lib/pathname2.rb', line 967

def open(*args, &block)
  File.open(self, *args, &block)
end

#opendir(&block) ⇒ Object

Dir.opendir



925
926
927
# File 'lib/pathname2.rb', line 925

def opendir(&block)
  Dir.open(self, &block)
end

#parentObject

Returns the parent directory of the given path.

Example:

Pathname2.new('/usr/local/bin').parent # => '/usr/local'


597
598
599
600
# File 'lib/pathname2.rb', line 597

def parent
  return self if root?
  self + '..' # Use our custom '+' method
end

#pretty_print(q) ⇒ Object

A custom pretty printer



840
841
842
843
844
845
846
# File 'lib/pathname2.rb', line 840

def pretty_print(q)
  if File::ALT_SEPARATOR
    q.text(to_s.tr(File::SEPARATOR, File::ALT_SEPARATOR))
  else
    q.text(to_s)
  end
end

#pstripObject

Removes all trailing slashes, if present. Non-destructive.

Example:

path = Pathname2.new('/usr/local/')
path.pstrip # => '/usr/local'


307
308
309
310
311
312
313
314
315
316
317
# File 'lib/pathname2.rb', line 307

def pstrip
  str = dup
  return str if str.empty?

  while [File::SEPARATOR, File::ALT_SEPARATOR].include?(str.to_s[-1].chr)
    str.strip!
    str.chop!
  end

  self.class.new(str)
end

#pstrip!Object

Performs the substitution of Pathname2#pstrip in place.



321
322
323
# File 'lib/pathname2.rb', line 321

def pstrip!
  replace(pstrip)
end

#read(*args) ⇒ Object

IO.read



877
878
879
# File 'lib/pathname2.rb', line 877

def read(*args)
  File.read(self, *args)
end

#readlines(*args) ⇒ Object

IO.readlines



882
883
884
# File 'lib/pathname2.rb', line 882

def readlines(*args)
  File.readlines(self, *args)
end

#realpathObject

Returns a real (absolute) pathname of self in the actual filesystem.

Unlike most Pathname2 methods, this one assumes that the path actually exists on your filesystem. If it doesn't, an error is raised. If a circular symlink is encountered a system error will be raised.

Example:

Dir.pwd                      # => /usr/local
File.exists?('foo')          # => true
Pathname2.new('foo').realpath # => /usr/local/foo


182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/pathname2.rb', line 182

def realpath
  File.stat(self) # Check to ensure that the path exists

  if File.symlink?(self)
    file = dup

    loop do
      file = File.join(File.dirname(file), File.readlink(file))
      break unless File.symlink?(file)
    end

    self.class.new(file).clean
  else
    self.class.new(Dir.pwd) + self
  end
end

#relative?Boolean

Returns whether or not the path is a relative path.

Example:

Pathname2.new('/usr/bin').relative? # => true
Pathname2.new('usr').relative?      # => false

Returns:

  • (Boolean)


737
738
739
740
741
742
743
# File 'lib/pathname2.rb', line 737

def relative?
  if @win
    PathIsRelativeW(wincode)
  else
    root == '.'
  end
end

#relative_path_from(base) ⇒ Object

Returns a relative path from the argument to the receiver. If self is absolute, the argument must be absolute too. If self is relative, the argument must be relative too. For relative paths, this method uses an imaginary, common parent path.

This method does not access the filesystem. It assumes no symlinks. You should only compare directories against directories, or files against files, or you may get unexpected results.

Raises an ArgumentError if it cannot find a relative path.

Examples:

path = Pathname2.new('/usr/local/bin')
path.relative_path_from('/usr/bin') # => "../local/bin"

path = Pathname2.new("C:\\WINNT\\Fonts")
path.relative_path_from("C:\\Program Files") # => "..\\WINNT\\Fonts"


621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
# File 'lib/pathname2.rb', line 621

def relative_path_from(base)
  base = self.class.new(base) unless base.is_a?(Pathname2)

  if absolute? != base.absolute?
    raise ArgumentError, 'relative path between absolute and relative path'
  end

  return self.class.new('.') if self == base
  return self if base == '.'

  # Because of the way the Windows version handles Pathname2#clean, we need
  # a little extra help here.
  if @win
    if root != base.root
      msg = 'cannot determine relative paths from different root paths'
      raise ArgumentError, msg
    end
    if base == '..' && (self != '..' || self != '.')
      raise ArgumentError, "base directory may not contain '..'"
    end
  end

  dest_arr = clean.to_a
  base_arr = base.clean.to_a
  dest_arr.delete('.')
  base_arr.delete('.')

  # diff_arr = dest_arr - base_arr

  while !base_arr.empty? && !dest_arr.empty? && base_arr[0] == dest_arr[0]
    base_arr.shift
    dest_arr.shift
  end

  if base_arr.include?('..')
    raise ArgumentError, "base directory may not contain '..'"
  end

  base_arr.fill('..')
  rel_path = base_arr + dest_arr

  if rel_path.empty?
    self.class.new('.')
  else
    self.class.new(rel_path.join(@sep))
  end
end

#remove_dir(*args) ⇒ Object

FileUtils.remove_dir



1101
1102
1103
# File 'lib/pathname2.rb', line 1101

def remove_dir(*args)
  FileUtils.remove_dir(self, *args)
end

#remove_file(*args) ⇒ Object

FileUtils.remove_file



1106
1107
1108
# File 'lib/pathname2.rb', line 1106

def remove_file(*args)
  FileUtils.remove_dir(self, *args)
end

#rename(name) ⇒ Object

File.rename



972
973
974
# File 'lib/pathname2.rb', line 972

def rename(name)
  File.rename(self, name)
end

#rm(*args) ⇒ Object Also known as: remove

FileUtils.rm



1049
1050
1051
# File 'lib/pathname2.rb', line 1049

def rm(*args)
  FileUtils.rm(self, *args)
end

#rm_f(*args) ⇒ Object

FileUtils.rm_f



1056
1057
1058
# File 'lib/pathname2.rb', line 1056

def rm_f(*args)
  FileUtils.rm_f(self, *args)
end

#rm_r(*args) ⇒ Object

FileUtils.rm_r



1061
1062
1063
# File 'lib/pathname2.rb', line 1061

def rm_r(*args)
  FileUtils.rm_r(self, *args)
end

#rm_rf(*args) ⇒ Object

FileUtils.rm_rf



1066
1067
1068
# File 'lib/pathname2.rb', line 1066

def rm_rf(*args)
  FileUtils.rm_rf(self, *args)
end

#rmtree(*args) ⇒ Object

FileUtils.rmtree



1071
1072
1073
# File 'lib/pathname2.rb', line 1071

def rmtree(*args)
  FileUtils.rmtree(self, *args)
end

#rootObject

Returns the root directory of the path, or '.' if there is no root directory.

On Unix, this means the '/' character. On Windows, this can refer to the drive letter, or the server and share path if the path is a UNC path.

Examples:

Pathname2.new('/usr/local').root       # => '/'
Pathname2.new('lib').root              # => '.'

On MS Windows:

Pathname2.new('C:\WINNT').root         # => 'C:'
Pathname2.new('\\some\share\foo').root # => '\\some\share'


510
511
512
513
514
515
516
517
518
519
520
521
522
523
# File 'lib/pathname2.rb', line 510

def root
  dir = '.'

  if @win
    wpath = FFI::MemoryPointer.from_string(wincode)
    if PathStripToRootW(wpath)
      dir = wpath.read_string(wpath.size).split("\000\000").first.tr(0.chr, '')
    end
  else
    dir = '/' if self =~ /^\//
  end

  self.class.new(dir)
end

#root?Boolean

Returns whether or not the path consists only of a root directory.

Examples:

Pathname2.new('/').root?    # => true
Pathname2.new('/foo').root? # => false

Returns:

  • (Boolean)


532
533
534
535
536
537
538
# File 'lib/pathname2.rb', line 532

def root?
  if @win
    PathIsRootW(wincode)
  else
    self == root
  end
end

#short_pathObject

Windows only

Returns the short path for a long path name.

Example:

path = Pathname2.new('C:\Program Files\Java')
path.short_path # => C:\Progra~1\Java.

Raises:

  • (NotImplementedError)


265
266
267
268
269
270
271
272
273
274
275
276
# File 'lib/pathname2.rb', line 265

def short_path
  raise NotImplementedError, 'not supported on this platform' unless @win

  buf = FFI::MemoryPointer.new(:char, MAXPATH)
  wpath = wincode

  size = GetShortPathNameW(wpath, buf, buf.size)

  raise SystemCallError.new('GetShortPathName', FFI.errno) if size == 0

  self.class.new(buf.read_bytes(size * 2).delete(0.chr))
end

File.symlink



977
978
979
# File 'lib/pathname2.rb', line 977

def symlink(old)
  File.symlink(old, self)
end

#sysopen(*args) ⇒ Object

IO.sysopen



887
888
889
# File 'lib/pathname2.rb', line 887

def sysopen(*args)
  IO.sysopen(self, *args)
end

#to_aObject

Splits a pathname into strings based on the path separator.

Examples:

Pathname2.new('/usr/local/bin').to_a # => ['usr', 'local', 'bin']
Pathname2.new('C:\WINNT\Fonts').to_a # => ['C:', 'WINNT', 'Fonts']


332
333
334
335
336
337
338
339
340
341
# File 'lib/pathname2.rb', line 332

def to_a
  # Split string by path separator
  if @win
    array = tr(File::SEPARATOR, File::ALT_SEPARATOR).split(@sep)
  else
    array = split(@sep)
  end
  array.delete('')    # Remove empty elements
  array
end

#touch(*args) ⇒ Object

FileUtils.touch



1081
1082
1083
# File 'lib/pathname2.rb', line 1081

def touch(*args)
  FileUtils.touch(*args)
end

#truncate(length) ⇒ Object

File.truncate



982
983
984
# File 'lib/pathname2.rb', line 982

def truncate(length)
  File.truncate(self, length)
end

#unc?Boolean

MS Windows only

Determines if the string is a valid Universal Naming Convention (UNC) for a server and share path.

Examples:

Pathname2.new("\\\\foo\\bar").unc?     # => true
Pathname2.new('C:\Program Files').unc? # => false

Returns:

  • (Boolean)

Raises:

  • (NotImplementedError)


550
551
552
553
# File 'lib/pathname2.rb', line 550

def unc?
  raise NotImplementedError, 'not supported on this platform' unless @win
  PathIsUNCW(wincode)
end

#undecorateObject

Windows only

Removes the decoration from a path string. Non-destructive.

Example:

path = Pathname2.new('C:Path\File.txt') path.undecorate # => C:PathFile.txt.



236
237
238
239
240
241
242
243
244
245
246
# File 'lib/pathname2.rb', line 236

def undecorate
  unless @win
    raise NotImplementedError, 'not supported on this platform'
  end

  wpath = FFI::MemoryPointer.from_string(wincode)

  PathUndecorateW(wpath)

  self.class.new(wpath.read_string(wpath.size).split("\000\000").first.tr(0.chr, ''))
end

#undecorate!Object

Windows only

Performs the substitution of Pathname2#undecorate in place.



252
253
254
# File 'lib/pathname2.rb', line 252

def undecorate!
  replace(undecorate)
end

#uptodate?(*args) ⇒ Boolean

FileUtils.uptodate?

Returns:

  • (Boolean)


1091
1092
1093
# File 'lib/pathname2.rb', line 1091

def uptodate?(*args)
  FileUtils.uptodate(self, *args)
end

#utime(atime, mtime) ⇒ Object

File.utime



987
988
989
# File 'lib/pathname2.rb', line 987

def utime(atime, mtime)
  File.utime(atime, mtime, self)
end