Recursive search in all directories and Ubdirectories of a given folder

Asked

Viewed 1,010 times

3

I am developing a script to scan a particular folder for certain files and delete them or move them to another folder, according to some rules I already got answered in this question and in this other question.

My idea was to abstract this search by saving all found files (either to move or to delete) into a list and later make a decision as to the operation, only that I don’t have much idea of how to do a search in a certain folder and its entire internal directory tree that are being found.

private static List<File> listarArquivos(File source, boolean condicao) {
    List<File> fileList = new ArrayList<>();

    File[] list = source.listFiles();

    for (File fl : list) {
        if (condicao) {
            fileList.add(fl);
            System.out.println(fl);
        }
    }

    return fileList;

}

This method only lists the subfolders and files from the main directory, but does not list more internal files and folders, how to do this recursively?

Note: in case of solutions using java-8, I ask for a brief explanation, as I am not very familiar with the new classes of this version.

2 answers

6

Just do a check if fl is a directory using File.isDirectory() and call the method again by passing fl as a parameter.

private static List<File> listarArquivos(File source) 
{
    List<File> fileList = new ArrayList<>();

    File[] list = source.listFiles();

    for (File fl : list) {
        if (!fl.isDirectory()) {
            fileList.add(fl);
            System.out.println(fl);
        }else{
            System.out.println(String.format("** Pasta: %s **", fl));
            listarArquivos(fl);
        }
    }

    return fileList;
}

2


Using Java 8 you can use the method walk class Files:

List<Path> lista = new ArrayList<>();

Files.walk(Paths.get("C:/D/Desktop/Workshop"))
        .filter(arquivo -> this.filtrar(arquivo))
        .forEach(lista::add);

Or if you wanted to return a list of File:

List<File> lista = new ArrayList<>();

Files.walk(Paths.get("C:/D/Desktop/Workshop"))
        .filter(arquivo -> this.filtrar(arquivo))
        .forEach(arquivo -> {
          lista.add(arquivo.toFile());
        });

whereas the method filtrar be it so (based in this answer):

private boolean filtrar(Path caminho) {
  return caminho.toString().matches("Copia - Copia\\.[^.]+$");
}

Files walk.

Returns a Stream that ociosamente(Lazy) populace with Path traversing the file tree starting with the initial file

Adapting to your method:

private static List<File> listarArquivos(File source, boolean condicao) throws IOException {
  List<File> fileList = new ArrayList<>();

  Files.walk(source.toPath()).forEach(arquivo -> {
    if (condicao) {
      fileList.add(arquivo.toFile());
    }
  });

  return fileList;
}
  • 2

    what is this method filtrar?

  • @Renan any method that can restrict the files added to the list. In case the suggested method could be used in this question that had been linked in the original question

  • What would that initial snippet of the answer look like, returning File array instead of Path?

  • @diegofm added in reply

  • I didn’t get that filtrar, which of the linked answers you saw this?

  • @diegofm I put any name. It would be a returning method boolean in which you would check the file name. If you want I put an example of what the method would look like

  • @diegofm added a method to the answer filtrar as an example

  • The problem is that if I create a filter method, I will have to create several because it’s not just the "copy" filter that I have. There are others I need to apply as well. The question code is adapted to the traditional form of previous versions because I had no idea how to use these new methods of java8

  • @diegofm You can put all the checks in the same method. But anyway it’s just an example of how you could filter the list before you put it on your return. You can remove that line that will add all the files from the tree

  • I think I understand the method of the end of the answer. That arquivo is a Path representation of each file that foreach travels through, correct?

  • @exact diegofm. The walk returns a Stream with all the Paths present in the tree. The forEach traverses the Stream assigning it to the variable of any name we put at the beginning of the method call. It could be f, a or something like that. I thought arquivo would be more meaningful

Show 6 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.