FileUtils head-scratcher

In one of my projects I need to move all files and subdirectories in a particular directory up on level.

e.g. mv * ..

When I wrote this in Ruby using FileUtils, it works the first time but subsequent runs fail and I don't understand why. The error doesn't make sense because the file/directory it is complaining about is always already there.

Here's the code:

require 'fileutils'

def makedir(name)
FileUtils.mkdir name unless File.exists?(name) && File.directory?(name)
end

makedir('dir')
Dir.chdir('dir') do
makedir('subdir')
Dir.chdir('subdir') do
   5.times { |i| FileUtils.touch i.to_s }
   makedir('subsubdir')
   Dir.chdir('subsubdir') do
     5.times { |i| FileUtils.touch i.to_s }
   end
end

subdir = Dir.glob("subdir/*")
FileUtils.mv subdir, '.', :verbose => true
end

The first run works. The second run fails.

cremes$ ruby a.rb
mv subdir/0 subdir/1 subdir/2 subdir/3 subdir/4 subdir/subsubdir .
cremes$ ruby a.rb
mv subdir/0 subdir/1 subdir/2 subdir/3 subdir/4 subdir/subsubdir .
An exception occurred running a.rb
    File exists - . (Errno::EEXIST)

Backtrace:
                { } in FileUtils.mv at /Volumes/spiff/cremes/dev/ruby/rubinius
                                       /lib/18/fileutils.rb:500
  { } in FileUtils.fu_each_src_dest at /Volumes/spiff/cremes/dev/ruby/rubinius
                                       /lib/18/fileutils.rb:1402
{ } in FileUtils.fu_each_src_dest0 at /Volumes/spiff/cremes/dev/ruby/rubinius
                                       /lib/18/fileutils.rb:1411
                          Array#each at kernel/bootstrap/array.rb:66
        FileUtils.fu_each_src_dest0 at /Volumes/spiff/cremes/dev/ruby/rubinius
                                       /lib/18/fileutils.rb:1409
         FileUtils.fu_each_src_dest at /Volumes/spiff/cremes/dev/ruby/rubinius
                                       /lib/18/fileutils.rb:1400
                       FileUtils.mv at /Volumes/spiff/cremes/dev/ruby/rubinius
                                       /lib/18/fileutils.rb:495
            { } in Object#__script__ at a.rb:19
                           Dir.chdir at kernel/common/dir.rb:68
                   Object#__script__ at a.rb:8
    Rubinius::CodeLoader#load_script at kernel/delta/codeloader.rb:65
    Rubinius::CodeLoader.load_script at kernel/delta/codeloader.rb:107
             Rubinius::Loader#script at kernel/loader.rb:618
               Rubinius::Loader#main at kernel/loader.rb:772

How do I get this to work *every* time?

cr

add

:force => true

to the call to
FileUtils.mv subdir, '.', :verbose => true

···

On 9/25/2011 12:22 PM, Chuck Remes wrote:

require 'fileutils'

def makedir(name)
  FileUtils.mkdir name unless File.exists?(name)&& File.directory?(name)
end

makedir('dir')
Dir.chdir('dir') do
  makedir('subdir')
  Dir.chdir('subdir') do
    5.times {|i| FileUtils.touch i.to_s }
    makedir('subsubdir')
    Dir.chdir('subsubdir') do
      5.times {|i| FileUtils.touch i.to_s }
    end
  end

  subdir = Dir.glob("subdir/*")
  FileUtils.mv subdir, '.', :verbose => true
end

Chuck, you should also be aware that you move directories up one level
as well. Is this what you want?

Kind regards

robert

···

On Sun, Sep 25, 2011 at 6:58 PM, Reid Thompson <reid.thompson@ateb.com> wrote:

On 9/25/2011 12:22 PM, Chuck Remes wrote:

require 'fileutils'

def makedir(name)
FileUtils.mkdir name unless File.exists?(name)&& File.directory?(name)
end

makedir('dir')
Dir.chdir('dir') do
makedir('subdir')
Dir.chdir('subdir') do
5.times {|i| FileUtils.touch i.to_s }
makedir('subsubdir')
Dir.chdir('subsubdir') do
5.times {|i| FileUtils.touch i.to_s }
end
end

subdir = Dir.glob("subdir/*")
FileUtils.mv subdir, '.', :verbose => true
end

add

:force => true

to the call to
FileUtils.mv subdir, '.', :verbose => true

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Robert, yes, my original message (first line) said that was my goal.

BTW, adding the :force => true option made this work. I am still puzzled as to why (I should probably look at the underlying implementation) but I am satisfied for now.

Thanks all for the help.

cr

···

On Sep 26, 2011, at 6:04 AM, Robert Klemme wrote:

On Sun, Sep 25, 2011 at 6:58 PM, Reid Thompson <reid.thompson@ateb.com> wrote:

On 9/25/2011 12:22 PM, Chuck Remes wrote:

require 'fileutils'

def makedir(name)
FileUtils.mkdir name unless File.exists?(name)&& File.directory?(name)
end

makedir('dir')
Dir.chdir('dir') do
makedir('subdir')
Dir.chdir('subdir') do
   5.times {|i| FileUtils.touch i.to_s }
   makedir('subsubdir')
   Dir.chdir('subsubdir') do
     5.times {|i| FileUtils.touch i.to_s }
   end
end

subdir = Dir.glob("subdir/*")
FileUtils.mv subdir, '.', :verbose => true
end

add

:force => true

to the call to
FileUtils.mv subdir, '.', :verbose => true

Chuck, you should also be aware that you move directories up one level
as well. Is this what you want?