Reputation: 2854
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
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
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
Reputation: 1
Dir.foreach(dir_path) {|f| File.delete("#{dir_path}/#{f}") if f != '.' && f != '..'}
Upvotes: -1
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
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
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
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