Pablo
Pablo

Reputation: 2854

Empty directory (delete all files)

What would be a safe and efficient way to delete all files in a directory in pure Ruby? I wrote

Dir.foreach(dir_path) {|f| File.delete(f) if f != '.' && f != '..'}

but it gives me a No such file or directory error.

Thank you.

Upvotes: 32

Views: 34946

Answers (9)

Ron Shinall
Ron Shinall

Reputation: 71

Here's another variation that's nice and succinct if you only have files or empty directories:

your_path.children.each.map(&:unlink)

Upvotes: 0

sarnold
sarnold

Reputation: 104080

You're probably getting that error because your current working directory doesn't match dir_path -- File.delete(f) is being given just the filename for a file in dir_path. (I hope you didn't have any important files in the current working directory with same names in the dir_path directory.)

You need to use File.join(dir_path, f) to construct the filename you wish to delete. You also need to figure out how you want to handle directories:

Dir.foreach(dir_path) do |f|
  fn = File.join(dir_path, f)
  File.delete(fn) if f != '.' && f != '..'
end

Errno::EISDIR: Is a directory - /tmp/testing/blubber
    from (irb):10:in `delete'
    from (irb):10
    from (irb):10:in `foreach'
    from (irb):10
    from :0

Upvotes: 14

MyroslavN
MyroslavN

Reputation: 1741

FileUtils.rm_rf Dir.glob("#{dir_path}/*") if dir_path.present?

Upvotes: 36

Ali Akbar
Ali Akbar

Reputation: 1

Dir.foreach(dir_path) {|f| File.delete("#{dir_path}/#{f}") if f != '.' && f != '..'}

Upvotes: -1

denis.peplin
denis.peplin

Reputation: 9851

Everybody suggest rm_rf, but the safer way is to use rm_f, which is an alias to rm force: true.

FileUtils.rm_f Dir.glob("#{dir_path}/*")

This method will not remove directories, it will only remove files: http://ruby-doc.org/stdlib-2.2.0/libdoc/fileutils/rdoc/FileUtils.html#method-c-rm

Upvotes: 11

LiamD
LiamD

Reputation: 2028

To tack on to MyroslavN, if you wanted to do it with Pathname (like with Rails.root, if it's a rails app) you want this:

FileUtils.rm_rf Dir.glob(Rails.root.join('foo', 'bar', '*'))

I'm posting this because I did a bad copypaste of his answer, and I accidentally wound up with an extra slash in my path:

Rails.root.join('foo', 'bar', '/*')

Which evaluates to /* because it sees it as a root path. And if you put that in the FileUtils.rm_rf Dir.glob it will attempt to recursively delete everything it can (probably limited by your permissions) in your filesystem.

Upvotes: 4

tcurdt
tcurdt

Reputation: 15808

The Tin Man almost got it right - but in case the directories are not empty use

Pathname.new(dir_path).children.each { |p| p.rmtree }

Upvotes: 3

the Tin Man
the Tin Man

Reputation: 160571

Now days, I like using the Pathname class when working on files or directories.

This should get you started:

Pathname.new(dir_path).children.each { |p| p.unlink }

unlink will remove directories or files, so if you have nested directories you want to preserve you'll have to test for them:

Removes a file or directory, using File.unlink if self is a file, or Dir.unlink as necessary.

Upvotes: 5

Mario Uher
Mario Uher

Reputation: 12397

What about FileUtils.rm_rf("#{dir_path}/.", secure: true)?

Upvotes: 78

Related Questions