lib/pleasant_path/pathname.rb
# Moves the file or directory indicated by the Pathname to
# +destination+, replacing any existing file or directory.
#
# If a block is given and a file or directory does exist at the
# destination, the block is called with the source and destination
# Pathnames, and the return value of the block is used as the new
# destination.  If the block returns the source Pathname or nil, the
# move is aborted.
#
# Creates any necessary parent directories of the destination.
# Returns the destination as a Pathname (or the source Pathname in the
# case that the move is aborted).
#
# *WARNING:* Due to system API limitations, the move is performed in
# two steps, non-atomically.  First, any file or directory existing
# at the destination is deleted.  Next, the source is moved to the
# destination.  The second step can fail independently of the first,
# e.g. due to insufficient disk space, leaving the file or directory
# previously at the destination deleted without replacement.
#
# @example Without a block
#   FileUtils.touch("file")
#
#   Pathname.new("file").move_as("dir/file")
#     # == Pathname.new("dir/file")
#
#   File.exist?("file")      # == false
#   File.exist?("dir/file")  # == true
#
# @example Error on older source
#   FileUtils.touch("file")
#   sleep 1
#   FileUtils.touch("file.new")
#
#   Pathname.new("file.new").move_as("file") do |source, destination|
#     if source.mtime < destination.mtime
#       raise "cannot replace newer file #{destination} with #{source}"
#     end
#     destination
#   end                      # == Pathname.new("file")
#
#   File.exist?("file.new")  # == false
#   File.exist?("file")      # == true
#
# @example Abort on conflict
#   FileUtils.touch("file1")
#   FileUtils.touch("file2")
#
#   Pathname.new("file1").move_as("file2") do |source, destination|
#     puts "#{source} not moved to #{destination} due to conflict"
#     nil
#   end                   # == Pathname.new("file1")
#
#   File.exist?("file1")  # == true
#   File.exist?("file2")  # == true
#
# @example New destination on conflict
#   FileUtils.touch("file1")
#   FileUtils.touch("file2")
#
#   Pathname.new("file1").move_as("file2") do |source, destination|
#     destination.available_name
#   end                     # == Pathname.new("file2_1")
#
#   File.exist?("file1")    # == false
#   File.exist?("file2")    # == true
#   File.exist?("file2_1")  # == true
#
# @overload move_as(destination)
#   @param destination [Pathname, String]
#   @return [Pathname]
#
# @overload move_as(destination, &block)
#   @param destination [Pathname, String]
#   @yieldparam source [Pathname]
#   @yieldparam destination [Pathname]
#   @yieldreturn [Pathname, nil]
#   @return [Pathname]
Moves the file or directory indicated by the Pathname to
+destination+, replacing any existing file or directory.

If a block is given and a file or directory does exist at the
destination, the block is called with the source and destination
Pathnames, and the return value of the block is used as the new
destination.  If the block returns the source Pathname or nil, the
move is aborted.

Creates any necessary parent directories of the destination.
Returns the destination as a Pathname (or the source Pathname in the
case that the move is aborted).

Due to system API limitations, the move is performed in
two steps, non-atomically.  First, any file or directory existing
at the destination is deleted.  Next, the source is moved to the
destination.  The second step can fail independently of the first,
e.g. due to insufficient disk space, leaving the file or directory
previously at the destination deleted without replacement.
Moves the file or directory indicated by the Pathname to + destination + replacing any existing file or directory . If a block is given and a file or directory does exist at the destination the block is called with the source and destination Pathnames and the return value of the block is used as the new destination . If the block returns the source Pathname or nil the move is aborted . Creates any necessary parent directories of the destination . Returns the destination as a Pathname ( or the source Pathname in the case that the move is aborted ) . Due to system API limitations the move is performed in two steps non - atomically . First any file or directory existing at the destination is deleted . Next the source is moved to the destination . The second step can fail independently of the first e . g . due to insufficient disk space leaving the file or directory previously at the destination deleted without replacement .
def move_as(destination)
    destination = destination.to_pathname
    if block_given? && destination.exist? && self.exist? && !File.identical?(self, destination)
      destination = (yield self, destination) || self
    end
    if destination != self
      if File.identical?(self, destination)
        File.rename(self, destination)
      else
        destination.delete!
        self.move(destination.make_dirname)
      end
    end
    destination
  end
def move_as ( destination ) destination = destination . to_pathname if block_given? && destination . exist? && self . exist? && ! File . identical? ( self , destination ) destination = ( yield self , destination ) || self end if destination != self if File . identical? ( self , destination ) File . rename ( self , destination ) else destination . delete! self . move ( destination . make_dirname ) end end destination end
Moves the file or directory indicated by the Pathname to
+destination+, replacing any existing file or directory.
Moves the file or directory indicated by the Pathname to + destination + replacing any existing file or directory .
# FileUtils.mv raises an ArgumentError when both paths refer to # the same file.  On case-insensitive file systems, this occurs # even when both paths have different casing.  We want to # disregard the ArgumentError at all times, and change the # filename casing when applicable.
destination
example
Without a block FileUtils.touch("file") Pathname.new("file").move_as("dir/file") # == Pathname.new("dir/file") File.exist?("file") # == false File.exist?("dir/file") # == true
Without a block FileUtils . touch ( " file " ) Pathname . new ( " file " ) . move_as ( " dir / file " ) # == Pathname . new ( " dir / file " ) File . exist? ( " file " ) # == false File . exist? ( " dir / file " ) # == true
example
Error on older source FileUtils.touch("file") sleep 1 FileUtils.touch("file.new") Pathname.new("file.new").move_as("file") do |source, destination| if source.mtime < destination.mtime raise "cannot replace newer file #{destination} with #{source}" end destination end # == Pathname.new("file") File.exist?("file.new") # == false File.exist?("file") # == true
Error on older source FileUtils . touch ( " file " ) sleep 1 FileUtils . touch ( " file . new " ) Pathname . new ( " file . new " ) . move_as ( " file " ) do |source destination| if source . mtime < destination . mtime raise " cannot replace newer file # { destination } with # { source } " end destination end # == Pathname . new ( " file " ) File . exist? ( " file . new " ) # == false File . exist? ( " file " ) # == true
example
Abort on conflict FileUtils.touch("file1") FileUtils.touch("file2") Pathname.new("file1").move_as("file2") do |source, destination| puts "#{source} not moved to #{destination} due to conflict" nil end # == Pathname.new("file1") File.exist?("file1") # == true File.exist?("file2") # == true
Abort on conflict FileUtils . touch ( " file1 " ) FileUtils . touch ( " file2 " ) Pathname . new ( " file1 " ) . move_as ( " file2 " ) do |source destination| puts " # { source } not moved to # { destination } due to conflict " nil end # == Pathname . new ( " file1 " ) File . exist? ( " file1 " ) # == true File . exist? ( " file2 " ) # == true
example
New destination on conflict FileUtils.touch("file1") FileUtils.touch("file2") Pathname.new("file1").move_as("file2") do |source, destination| destination.available_name end # == Pathname.new("file2_1") File.exist?("file1") # == false File.exist?("file2") # == true File.exist?("file2_1") # == true
New destination on conflict FileUtils . touch ( " file1 " ) FileUtils . touch ( " file2 " ) Pathname . new ( " file1 " ) . move_as ( " file2 " ) do |source destination| destination . available_name end # == Pathname . new ( " file2_1 " ) File . exist? ( " file1 " ) # == false File . exist? ( " file2 " ) # == true File . exist? ( " file2_1 " ) # == true
overload
move_as(destination) @param destination [Pathname, String] @return [Pathname]
move_as ( destination ) @param destination [ Pathname String ] @return [ Pathname ]
overload
None