I am trying to create a File Searching Utility that finds all Files with a given Name which searches all Folders (Sub Directories, and Sub Directories of Sub Directories) in a given Directory. I was thinking of a way to use For Loops, or For Each, but that would mean I would need a For Loop or a For Each, for each sub directory. Basically output a line for each file found.

Example:

Input File Name: Hello.txt
Input Inital Directory: C:/Users/GeoDoX/Documents/

File: Hello.txt
Path: C:\Users\GeoDoX\Documents\

C:\Users\GeoDoX\Documents\Hello.txt
C:\Users\GeoDoX\Documents\Test\Hello.txt
C:\Users\GeoDoX\Documents\Test\Hello\Hello.txt

Obviously there is some recursion, and I can't think of where to start, or even how to get a list of directories in the current directory.

PS: I want this to support Wild Cards (.txt, *.pdf, etc, as well as (name)., but not .)

Here's what I have so far though.

package com.github.geodox.filefinder.main;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * @author GeoDoX
 *
 * FileFinder.java
 */
public class FileFinder
{

    public static void main(String[] args)
    {
        new FileFinder();
    }

    private FileFinder()
    {
        InputStreamReader reader = new InputStreamReader(System.in);    /* Needed for getting Input from User, Passed to BufferedReader */
        BufferedReader input = new BufferedReader(reader);              /* Gets user input */
        File file = null;       /* File being Searched for, Can be wild card */
        Path dir = null;        /* Directory for searching for the file(s) requested in this Path, and Sub Paths */

        try
        {
            /* Get File */
            log("Input File Name: ");
            file = new File(input.readLine());

            /* Get Directory */
            log("Input Inital Directory: ");
            dir = Paths.get(input.readLine());
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }

        outputFileAndPath(file, dir);

    }

    private void outputFileAndPath(File file, Path dir)
    {
        /* Print the File and Path info */

        log("\n");
        log("File: " + file);
        log("\n");
        log("Path: " + dir);
    }

    private void log(Object aObject)
    {
        /* Simple method for printing */
        System.out.print(aObject);
    }

    private void logln(Object aObject)
    {
        /* Simple method for printing a line */
        System.out.println(aObject);
    }

}

Sample Input and Output:

Input File Name: Hello.txt
Input Inital Directory: C:/Users/GeoDoX/Desktop/

File: Hello.txt
Path: C:\Users\GeoDoX\Desktop

Recursion is the answer if you want to hand-code this. The basic structure goes like (pseudo code):

method searchDir(Dir d) {
   for each File f in d
        if f is an ordinary file check it against the search criteria
        if f is a directory call searchDir(f)

NB: By now you should be using the NIO file classes (Path and Files) which include a FileVisitor implementation that walks the directory structure for you, and handles symbolic links etc properly

If I didn't want to code it myself, I assume by what you said, the NIO file classes has methods to do this?

EDIT:
Nevermind, I found it.
Files.walkFileTree(start, visitor);
But what is a FileVisitor, and how do I use it?

PM me them if you don't mind :)

This is a public forum for everyone to contribute and everyone to benefit - so no PMs. Here's a simple eg that adds up the total size of a dir and all its sub dirs by visiting every file in the structure. It uses a simple stack to keep track of the nested dirs as it enters and leaves them:

class SimpleSizeWalker extends SimpleFileVisitor<Path> {
    // simple (simplest?) code to list sizes of dirs and sub-dirs

    Deque<Long> dirStack = new ArrayDeque<>(); // current directory sizes 

    @Override
    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
        dirStack.push(new Long(0));
        return CONTINUE;
    }

    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attr) {
        // add file size to size at top of stack
        dirStack.push(dirStack.pop() + attr.size());
        return CONTINUE;
    }

    @Override
    public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
        long size = dirStack.pop();
        System.out.println(dir + " = " + size + " bytes");
        if (!dirStack.isEmpty()) // add this dir size to parent's size
            dirStack.push(dirStack.pop() + size);
        return CONTINUE;
    }
}

and use that with something like

Path dirPath = FileSystems.getDefault().getPath("my dir path");
SimpleSizeWalker ssw = new SimpleSizeWalker();
Files.walkFileTree(dirPath, ssw);

... or here's a even simpler one - it searches for a given file name anywhere in the directory tree...

class MySimpleFileFinder extends SimpleFileVisitor<Path> {

    String target;

     public MySimpleFileFinder(String target) {
        this.target = target;
    }

    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attr) {
        if (file.getFileName().toString().equalsIgnoreCase(target)) {
            System.out.println("Found " + file);
            return TERMINATE;
        }
        return CONTINUE;
    }
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.