[groovy-user] Best way to delete certain files and directories recursively

2,409 views
Skip to first unread message

Mohamed Seifeddine

unread,
May 11, 2012, 10:13:01 AM5/11/12
to us...@groovy.codehaus.org
aFile.eachFileRecurse {

   if ( it.getName() in ['aDirectoryName', 'abc.xml', 'def.xml' ] ) {
        it.isDirectory() ? it.deleteDir() : it.delete()
   }

}

The above won't work, since recurse method will walk through all files, and if a directory is deleted before its files have been iterated over, 
the recurse iteration will break since the files supposed to be iterated next no longer exists ( they used to be in the deleted directory ).

So, what is the best way to do the above? 

This is what I have, that works, although not perfect, and also way to much code


    def dirs  = []
     
    new File(filename).eachFileRecurse { file ->
                
        if ( file.getName() in  ['aDirectoryName', 'abc.xml', 'def.xml' ]  ) {
            
            if ( file.isDirectory() ) {
                dirs << file
            }
            else {
                print "Deleting ${file.getAbsolutePath() }: "
      println file.delete() 
            }
        }
    }
    dirs.each { file ->
        print "Deleting ${file.getAbsolutePath() }: "
        println file.deleteDir()
    }

Is there a better way?

Thanks, Mo

Nagai Masato

unread,
May 12, 2012, 12:36:04 AM5/12/12
to us...@groovy.codehaus.org
I wrote a example that adding another "eachFileRecurse", which allows
deleting files in closure, to File class.
Try it.

https://gist.github.com/f52e11ef282a785f65f4

--
Nagai Masato | @nagai_masato | nagaima...@gmail.com |
nagaimasato.blogspot.com
---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email


Nagai Masato

unread,
May 12, 2012, 12:59:40 AM5/12/12
to us...@groovy.codehaus.org
Or more shorter example without ExpandMetaClass is here:
https://gist.github.com/2664226

Nagai Masato

Paul Holt

unread,
May 12, 2012, 8:34:52 AM5/12/12
to us...@groovy.codehaus.org
Use Ant builder tasks.
--
Paul Holt

Paul Holt

unread,
May 12, 2012, 8:37:47 AM5/12/12
to us...@groovy.codehaus.org
http://groovy.codehaus.org/Using+Ant+from+Groovy 

Have a look at some of the examples on that page and see if AntBuilder fits what you're trying to do.
--
Paul Holt

Bob Brown

unread,
May 12, 2012, 9:06:06 AM5/12/12
to us...@groovy.codehaus.org
You may want to take a look at:

http://groovy.codehaus.org/Using+Ant+from+Groovy

This allows you to use the features of ant from groovy...via AntBuilder.

grails uses antbuilder, as discussed here:

http://mrhaki.blogspot.com.au/2009/12/grails-goodness-cleaning-up-before-war.html

Bob

Sent from my iPad

Dinko Srkoc

unread,
May 12, 2012, 6:22:05 PM5/12/12
to us...@groovy.codehaus.org
`File.traverse` may do the trick:

8<--------------------------------
import static groovy.io.FileVisitResult.*

def toDelete = ['aDirectoryName', 'abc.xml', 'def.xml']

new File(filename).traverse(
preDir: {
if (it.directory && it.name in toDelete) {
it.deleteDir()
return SKIP_SUBTREE
}
}
) { if (it.file && it.name in toDelete) it.delete() }
-------------------------------->8

Cheers,
Dinko

Paul Holt

unread,
May 13, 2012, 9:40:06 AM5/13/12
to us...@groovy.codehaus.org
snap!
--
Paul Holt

Bob Brown

unread,
May 13, 2012, 6:06:54 PM5/13/12
to us...@groovy.codehaus.org
"Great minds...'", and all that!

Sent from my iPad

Nagai Masato

unread,
May 13, 2012, 11:40:18 PM5/13/12
to us...@groovy.codehaus.org
Cool. I never knew the way.
--
Nagai Masato | @nagai_masato | nagaima...@gmail.com |
nagaimasato.blogspot.com

Mohamed Seifeddine

unread,
May 14, 2012, 3:47:57 AM5/14/12
to us...@groovy.codehaus.org
Nice Dinko ;) 

I haven't tested it, but it looks as if it should work :)


// Moe

Mohamed Seifeddine

unread,
May 14, 2012, 10:38:25 AM5/14/12
to us...@groovy.codehaus.org
It should be said that preDir is not the first place where the directory is processed but infact will be processed in the second closure first, then in preDir and then all its files again in the second closure, and then end with postDir. 

Is this a bug? Shouldn't predir run before the second closure ? ( Not a big issue but still ... the docs states that this should run before the direcotory is processed )

import groovy.io.FileVisitResult
int i = 50;
new File("D:/Random/TMP/").traverse(
   preDir: {
       if ( i-- <= 0 ) 
           return FileVisitResult.TERMINATE
           
       println "PRE  $i : $it.absolutePath"
       //println it.deleteDir()
       //return FileVisitResult.SKIP_SUBTREE
   },
   
   postDir: {
       println "POS  $i : $it.absolutePath"
   }, { 

if ( it.isDirectory() ) {
   println "AFT  $i : $it.absolutePath"
}
else 
   println "FILE $i : $it.absolutePath"
})



Outputs:

AFT  50 : D:\Random\TMP\Folder 0
PRE  49 : D:\Random\TMP\Folder 0
POS  49 : D:\Random\TMP\Folder 0
AFT  49 : D:\Random\TMP\Folder 1
PRE  48 : D:\Random\TMP\Folder 1
FILE 48 : D:\Random\TMP\Folder 1\folder1file0.txt
FILE 48 : D:\Random\TMP\Folder 1\folder1file1.txt
POS  48 : D:\Random\TMP\Folder 1
AFT  48 : D:\Random\TMP\Folder 2
PRE  47 : D:\Random\TMP\Folder 2
FILE 47 : D:\Random\TMP\Folder 2\folder2file0.txt
FILE 47 : D:\Random\TMP\Folder 2\folder2file1.txt
AFT  47 : D:\Random\TMP\Folder 2\folder2folder0
PRE  46 : D:\Random\TMP\Folder 2\folder2folder0
FILE 46 : D:\Random\TMP\Folder 2\folder2folder0\folder2folder0file0.txt
FILE 46 : D:\Random\TMP\Folder 2\folder2folder0\folder2folder0file1.txt
POS  46 : D:\Random\TMP\Folder 2\folder2folder0
POS  46 : D:\Random\TMP\Folder 2


Directory structure in TMP:

Folder 0:

Folder 1:
folder1file0.txt  folder1file1.txt

Folder 2:
folder2file0.txt  folder2file1.txt  folder2folder0:
  folder2folder0file0.txt  folder2folder0file1.txt

Dinko Srkoc

unread,
May 14, 2012, 11:09:50 AM5/14/12
to us...@groovy.codehaus.org
On 14 May 2012 16:38, Mohamed Seifeddine <msei...@gmail.com> wrote:
> It should be said that preDir is not the first place where the directory is
> processed but infact will be processed in the second closure first, then in
> preDir and then all its files again in the second closure, and then end with
> postDir.

Yes, the second closure is processed first, then the `preDir`. That
bothered me somewhat as well. Also, whether the next closure is called
depends on what predecessors returned.

My initial attempt was to call `traverse(Closure)`, without the map
parameter, and return `SKIP_SUBTREE` from there, but it turned out
that `SKIP_SUBTREE`, unlike `TERMINATE` or `SKIP_SIBLINGS`, is
evaluated only as a result of the `preDir` call.

Cheers,
Dinko

paulk_asert

unread,
May 14, 2012, 8:19:05 PM5/14/12
to us...@groovy.codehaus.org
Hmmm... looks like there is a bug there. If FileType is set to FILES,
everything seems OK, but otherwise, predir is being called out of order. The
behaviour is meant to mimic what the NIO2 traverse in Java7 would do.

--
View this message in context: http://groovy.329449.n5.nabble.com/Best-way-to-delete-certain-files-and-directories-recursively-tp5705378p5709655.html
Sent from the groovy - user mailing list archive at Nabble.com.
Reply all
Reply to author
Forward
0 new messages