code: public static void eachFileRecurse(final File self, final FileType fileType, @ClosureParams(value = SimpleType.class, options = "java.io.File") final Closure closure)
              throws FileNotFoundException, IllegalArgumentException {
          checkDir(self);
          final File[] files = self.listFiles();
          // null check because of http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4803836
          if (files == null) return;
          for (File file : files) {
              if (file.isDirectory()) {
                  if (fileType != FileType.FILES) closure.call(file);
                  eachFileRecurse(file, fileType, closure);
              } else if (fileType != FileType.DIRECTORIES) {
                  closure.call(file);
              }
          }
      }
docs: Processes each descendant file in this directory and any sub-directories.
  Processing consists of potentially calling <code>closure</code> passing it the current
  file (which may be a normal file or subdirectory) and then if a subdirectory was encountered,
  recursively processing the subdirectory. Whether the closure is called is determined by whether
  the file was a normal file or subdirectory and the value of fileType.
  
  @param self     a File (that happens to be a folder/directory)
  @param fileType if normal files or directories or both should be processed
  @param closure  the closure to invoke on each file
  @throws FileNotFoundException    if the given directory does not exist
  @throws IllegalArgumentException if the provided File object does not represent a directory
  @since 1.7.1