Walking through a directory recursively

Hierarchical file systems are the way we store most of our data. Groovy can help to build code that needs to go through a dense forest of directory trees.

In this recipe, we will cover different ways of walking through a directory tree using Groovy I/O awesomeness.

Getting ready

Let's assume that we need to walk through the current working directory. We can define the currentDir variable of java.io.File type that points to it:

def currentDir = new File('.')

To test this recipe, you can use either a script file that you launch with the groovy command or the groovysh/groovyConsole prompt.

How to do it...

As you probably know, the java.io.File class already provides the list and listFiles methods that return a collection of first-level elements (files and directories) in a directory represented by a File object. Using a recursive function, you can easily traverse the subfolders found in the first-level folders.

  1. However, Groovy already provides more concise methods that use recursion internally to traverse a directory. One of them is the eachFileRecurse method. It takes a closure as an input parameter, which is called for every file or directory entry that is found:
    currentDir.eachFileRecurse { File file ->
      println file.name
    }
  2. If you need to walk recursively only through the directories, then you can use the eachDirRecurse method instead:
    currentDir.eachDirRecurse { File dir ->
      println dir.name
    }
  3. If you only need to go through the files, then you can pass an additional parameter to eachFileRecurse, which is a value of a groovy.io.FileType enumeration (you'll need to add an additional import at the beginning of your script or groovysh/groovyConsole prompt):
    import groovy.io.FileType
    ...
    
    currentDir.eachFileRecurse(FileType.FILES) { File file ->
      println file.name
    }

How it works...

The previous code recursively prints the names of all the files and/or directories in the current directory tree. The recursive walk performs a depth-first search. That means that when the search goes through a list of children and encounters a directory, then it goes (deeper) inside that directory first before returning to process the remaining children. The order in which files and directories are processed depends on the implementation of the file system.

There's more...

Groovy also adds the eachFile and eachDir methods to a java.io.File class that you can use to iterate through the first-level elements only (just like listFiles). As other each-methods, they take a closure as an input parameter. You can use that to build a recursive function in a similar way as you would use it with the listFiles method. But instead of defining a separate function, you can also make use of Groovy's closure that is capable of creating a copy of itself with the help of the trampoline method:

    currentDir.eachFile { File file ->
      println file.name
      if (file.isDirectory()) {
        file.eachFile( trampoline() )
      }
    }

The code snippet above does exactly the same thing as the previous code examples. The "magic" trampoline method passes a copy of the parent closure to the nested eachFile call, a copy of the parent closure and makes it behave like a recursive function.

The previous example is very condensed, but it's not as obvious and easy to read compared to the initially described methods.

Since v1.7.1, Groovy has also introduced a very powerful traverse method in the java.io.File class. In its simplest form, it does the same as eachFileRecurse:

currentDir.traverse { File file ->
  println file.name
}

The traverse method has an overloaded version that also accepts a Map of additional parameters, which allows you to control various aspects of directory traversing behavior.

More advanced traverse options are described in the Searching for files recipe.

See also

The following recipes contain some additional information on the topics discussed in this recipe:

  • Searching for files
  • The Defining code as data in Groovy recipe in Chapter 3, Using Groovy language features

Also, it's worth examining the Groovydoc for the File, FileType, and Closure classes:

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.140.195.225