JamesEggers
JamesEggers

Reputation: 12935

Recursive Patterned File Delete in Ruby/Rake

I am attempting to delete files based on a pattern from all directories contained in a given path. I have the following but it acts like an infinite loop. When I cancel out of the loop, no files are deleted. Where am I going wrong?

def recursive_delete (dirPath, pattern)
    if (defined? dirPath and  defined? pattern && File.exists?(dirPath))
        stack = [dirPath]

        while !stack.empty?
            current = stack.delete_at(0)
            Dir.foreach(current) do |file|
                if File.directory?(file)
                    stack << current+file
                else
                    File.delete(dirPath + file) if (pattern).match(file)
                end
            end
        end

    end
end

# to call:
recursive_delete("c:\Test_Directory\", /^*.cs$/)

Upvotes: 13

Views: 8534

Answers (4)

Eduardo Santana
Eduardo Santana

Reputation: 6110

Since you are using Rake, I would use the clean task to delete files:

require 'rake/clean'
outfiles = Rake::FileList.new("**/*.out")
CLEAN << outfiles

Now if you run rake -T you will see that we have a clean and a clobber task.

rake clean    # Remove any temporary products
rake clobber  # Remove any generated files

If you run rake clean it will delete all files with .out extension.

With this approach you can choose to delete temporary files or generated files. Use the task clobber for deleting generated files, like this:

CLOBBER << Rake::FileList.new("**/*.gen")

You can see he definition of these tasks on the source code here.

Upvotes: 0

Ben Lee
Ben Lee

Reputation: 53349

You don't need to re-implement this wheel. Recursive file glob is already part of the core library.

Dir.glob('C:\Test_Directory\**\*.cs').each { |f| File.delete(f) }

Dir#glob lists files in a directory and can accept wildcards. ** is a super-wildcard that means "match anything, including entire trees of directories", so it will match any level deep (including "no" levels deep: .cs files in C:\Test_Directory itself will also match using the pattern I supplied).

@kkurian points out (in the comments) that File#delete can accept a list, so this could be simplified to:

File.delete(*Dir.glob('C:\Test_Directory\**\*.cs'))

Upvotes: 33

kite
kite

Reputation: 1548

another ruby one liner shortcuts using FileUtils to recursive delete files under a directory

FileUtils.rm Dir.glob("c:/temp/**/*.so")

even shorter:

FileUtils.rm Dir["c:/temp/**/*.so"]

another complex usage: multiple patterns (multiple extension in different directory). Warning you cannot use Dir.glob()

FileUtils.rm Dir["c:/temp/**/*.so","c:/temp1/**/*.txt","d:/temp2/**/*.so"] 

Upvotes: 11

maerics
maerics

Reputation: 156534

Since you're using Rake already you can use the convenient FileList object. For example:

require 'rubygems'
require 'rake'

FileList['c:/Test_Directory/**/*.cs'].each {|x| File.delete(x)}

Upvotes: 12

Related Questions