[java] Java - Search for files in a directory

This is supposed to be simple, but I can't get it - "Write a program that searches for a particular file name in a given directory." I've found a few examples of a hardcoded filename and directory, but I need both the dir and file name to be as entered by the user.

public static void main(String[] args) {
    String fileName = args[0]; // For the filename declaration
    String directory;     
    boolean found;

    File dir = new File(directory);

    File[] matchingFiles = dir.listFiles(new FilenameFilter() {
        public boolean accept(File dir, String fileName) {
            return true;
        }
    });

}

This question is related to java file search directory

The answer is


Using Java 8+ features we can write the code in few lines:

protected static Collection<Path> find(String fileName, String searchDirectory) throws IOException {
    try (Stream<Path> files = Files.walk(Paths.get(searchDirectory))) {
        return files
                .filter(f -> f.getFileName().toString().equals(fileName))
                .collect(Collectors.toList());

    }
}

Files.walk returns a Stream<Path> which is "walking the file tree rooted at" the given searchDirectory. To select the desired files only a filter is applied on the Stream files. It compares the file name of a Path with the given fileName.

Note that the documentation of Files.walk requires

This method must be used within a try-with-resources statement or similar control structure to ensure that the stream's open directories are closed promptly after the stream's operations have completed.

I'm using the try-resource-statement.


For advanced searches an alternative is to use a PathMatcher:

protected static Collection<Path> find(String searchDirectory, PathMatcher matcher) throws IOException {
    try (Stream<Path> files = Files.walk(Paths.get(searchDirectory))) {
        return files
                .filter(matcher::matches)
                .collect(Collectors.toList());

    }
}

An example how to use it to find a certain file:

public static void main(String[] args) throws IOException {
    String searchDirectory = args[0];
    String fileName = args[1];
    PathMatcher matcher = FileSystems.getDefault().getPathMatcher("regex:.*" + fileName);
    Collection<Path> find = find(searchDirectory, matcher);
    System.out.println(find);
}

More about it: Oracle Finding Files tutorial


I have used a different approach to search for a file using stack.. keeping in mind that there could be folders inside a folder. Though its not faster than windows search(and I was not expecting that though) but it definitely gives out correct result. Please modify the code as you wish to. This code was originally made to extract the file path of certain file extension :). Feel free to optimize.

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Deepankar Sinha
 */
public class GetList {
    public List<String> stack;
    static List<String> lnkFile;
    static List<String> progName;

    int index=-1;
    public static void main(String args[]) throws IOException
    {

        //var-- progFile:Location of the file to be search. 
        String progFile="C:\\";
        GetList obj=new GetList();
        String temp=progFile;
        int i;
        while(!"&%@#".equals(temp))
        {
            File dir=new File(temp);
            String[] directory=dir.list();
            if(directory!=null){
            for(String name: directory)
            {
                if(new File(temp+name).isDirectory())
                    obj.push(temp+name+"\\");
                else
                    if(new File(temp+name).isFile())
                    {
                        try{
                            //".exe can be replaced with file name to be searched. Just exclude name.substring()... you know what to do.:)
                        if(".exe".equals(name.substring(name.lastIndexOf('.'), name.length())))
                        {
                            //obj.addFile(temp+name,name);
                            System.out.println(temp+name);
                        }
                        }catch(StringIndexOutOfBoundsException e)
                        {
                            //debug purpose
                            System.out.println("ERROR******"+temp+name);
                        }

                    }
            }}
            temp=obj.pop();
        }
        obj.display();

//        for(int i=0;i<directory.length;i++)
//        System.out.println(directory[i]);
    }

    public GetList() {
        this.stack = new ArrayList<>();
        this.lnkFile=new ArrayList<>();
        this.progName=new ArrayList<>();
    }
    public void push(String dir)
    {
        index++;
        //System.out.println("PUSH : "+dir+" "+index);
        this.stack.add(index,dir);

    }
    public String pop()
    {
        String dir="";
        if(index==-1)
            return "&%@#";
        else
        {
            dir=this.stack.get(index);
            //System.out.println("POP : "+dir+" "+index);
            index--;

        }
        return dir;
    }

    public void addFile(String name,String name2)
    {
        lnkFile.add(name);
        progName.add(name2);
    }

    public void display()
    {
        GetList.lnkFile.stream().forEach((lnkFile1) -> {
            System.out.println(lnkFile1);
        });
    }

}

public class searchingFile 
{
     static String path;//defining(not initializing) these variables outside main 
     static String filename;//so that recursive function can access them
     static int counter=0;//adding static so that can be accessed by static methods 

    public static void main(String[] args) //main methods begins
    {
        Scanner sc=new Scanner(System.in);
        System.out.println("Enter the path : ");
        path=sc.nextLine(); //storing path in path variable
        System.out.println("Enter file name : ");
        filename=sc.nextLine(); //storing filename in filename variable
        searchfile(path);//calling our recursive function and passing path as argument
        System.out.println("Number of locations file found at : "+counter);//Printing occurences

    }

    public static String searchfile(String path)//declaring recursive function having return 
                                                //type and argument both strings

    {
        File file=new File(path);//denoting the path
        File[] filelist=file.listFiles();//storing all the files and directories in array

    for (int i = 0; i < filelist.length; i++) //for loop for accessing all resources
    {
        if(filelist[i].getName().equals(filename))//if loop is true if resource name=filename
        {
            System.out.println("File is present at : "+filelist[i].getAbsolutePath());
            //if loop is true,this will print it's location
            counter++;//counter increments if file found
        }
        if(filelist[i].isDirectory())// if resource is a directory,we want to inside that folder
        {
            path=filelist[i].getAbsolutePath();//this is the path of the subfolder
            searchfile(path);//this path is again passed into the searchfile function 
                             //and this countinues untill we reach a file which has
                             //no sub directories

        }
    }
    return path;// returning path variable as it is the return type and also 
                // because function needs path as argument.

    }   
}

With **Java 8* there is an alternative that use streams and lambdas:

public static void recursiveFind(Path path, Consumer<Path> c) {
  try (DirectoryStream<Path> newDirectoryStream = Files.newDirectoryStream(path)) {
    StreamSupport.stream(newDirectoryStream.spliterator(), false)
                 .peek(p -> {
                   c.accept(p);
                   if (p.toFile()
                        .isDirectory()) {
                     recursiveFind(p, c);
                   }
                 })
                 .collect(Collectors.toList());
  } catch (IOException e) {
    e.printStackTrace();
  }
}

So this will print all the files recursively:

recursiveFind(Paths.get("."), System.out::println);

And this will search for a file:

recursiveFind(Paths.get("."), p -> { 
  if (p.toFile().getName().toString().equals("src")) {
    System.out.println(p);
  }
});

This method will recursively search thru each directory starting at the root, until the fileName is found, or all remaining results come back null.

public static String searchDirForFile(String dir, String fileName) {
    File[] files = new File(dir).listFiles();
    for(File f:files) {
        if(f.isDirectory()) {
            String loc = searchDirForFile(f.getPath(), fileName);
            if(loc != null)
                return loc;
        }
        if(f.getName().equals(fileName))
            return f.getPath();
    }
    return null;
}

This looks like a homework question, so I'll just give you a few pointers:

Try to give good distinctive variable names. Here you used "fileName" first for the directory, and then for the file. That is confusing, and won't help you solve the problem. Use different names for different things.

You're not using Scanner for anything, and it's not needed here, get rid of it.

Furthermore, the accept method should return a boolean value. Right now, you are trying to return a String. Boolean means that it should either return true or false. For example return a > 0; may return true or false, depending on the value of a. But return fileName; will just return the value of fileName, which is a String.


I tried many ways to find the file type I wanted, and here are my results when done.

public static void main( String args[]){
final String dir2 = System.getProperty("user.name"); \\get user name 
String path = "C:\\Users\\" + dir2; 
digFile(new File(path)); \\ path is file start to dig
    
   for (int i = 0; i < StringFile.size(); i++) {
         
   System.out.println(StringFile.get(i));
        
    }
 }

private void digFile(File dir) {

    FilenameFilter filter = new FilenameFilter() {
        public boolean accept(File dir, String name) {
            return name.endsWith(".mp4");
        }
    };      
    String[] children = dir.list(filter);

   
    if (children == null) {
        return;
    } else {
        for (int i = 0; i < children.length; i++) {
            StringFile.add(dir+"\\"+children[i]);

        }
    }

    File[] directories;
    directories = dir.listFiles(new FileFilter() {
        @Override
        public boolean accept(File file) {
            return file.isDirectory();
        }
    
        public boolean accept(File dir, String name) {
            return !name.endsWith(".mp4");
        }
    });
        
   if(directories!=null)
   {
       for (File directory : directories) {
           digFile(directory);
       }
   }
    
}

If you want to use a dynamic filename filter you can implement FilenameFilter and pass in the constructor the dynamic name.

Of course this implies taht you must instantiate every time the class (overhead), but it works

Example:

public class DynamicFileNameFilter implements FilenameFilter {

    private String comparingname;

    public DynamicFileNameFilter(String comparingName){
        this.comparingname = comparingName;
    }

    @Override
    public boolean accept(File dir, String name) {
        File file = new File(name);

        if (name.equals(comparingname) && !file.isDirectory())
            return false;

        else
            return true;
    }

}

then you use where you need:

FilenameFilter fileNameFilter = new DynamicFileNameFilter("thedynamicNameorpatternYouAreSearchinfor");
File[] matchingFiles = dir.listFiles(fileNameFilter);

The Following code helps to search for a file in directory and open its location

import java.io.*;
import java.util.*;
import java.awt.Desktop;
public class Filesearch2 {


    public static void main(String[] args)throws IOException {        
        Filesearch2 fs = new Filesearch2();
        Scanner scan = new Scanner(System.in);
        System.out.println("Enter the file to be searched.. " );
        String name = scan.next();
        System.out.println("Enter the directory where to search ");
        String directory = scan.next();
        fs.findFile(name,new File(directory));
    }
    public void findFile(String name,File file1)throws IOException
    {      
        File[] list = file1.listFiles();       
        if(list!=null)  
     {                          
        for(File file2 : list)
        {            
            if (file2.isDirectory())
            {
                findFile(name,file2);             
            }
            else if (name.equalsIgnoreCase(file2.getName()))
            {                                                              
                System.out.println("Found");                
                System.out.println("File found at : "+file2.getParentFile());
                System.out.println("Path diectory: "+file2.getAbsolutePath());
                String p1 = ""+file2.getParentFile();
                File f2 = new File(p1);
                Desktop.getDesktop().open(f2);                               
            }                      
        }        
      }
    }        
}

Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to file

Gradle - Move a folder from ABC to XYZ Difference between opening a file in binary vs text Angular: How to download a file from HttpClient? Python error message io.UnsupportedOperation: not readable java.io.FileNotFoundException: class path resource cannot be opened because it does not exist Writing JSON object to a JSON file with fs.writeFileSync How to read/write files in .Net Core? How to write to a CSV line by line? Writing a dictionary to a text file? What are the pros and cons of parquet format compared to other formats? Find a file by name in Visual Studio Code Search all the occurrences of a string in the entire project in Android Studio Java List.contains(Object with field value equal to x) Trigger an action after selection select2 How can I search for a commit message on GitHub? SQL search multiple values in same field Find a string by searching all tables in SQL Server Management Studio 2008 Search File And Find Exact Match And Print Line? Java - Search for files in a directory How to put a delay on AngularJS instant search?

Examples related to directory

Moving all files from one directory to another using Python What is the reason for the error message "System cannot find the path specified"? Get folder name of the file in Python How to rename a directory/folder on GitHub website? Change directory in Node.js command prompt Get the directory from a file path in java (android) python: get directory two levels up How to add 'libs' folder in Android Studio? How to create a directory using Ansible Troubleshooting misplaced .git directory (nothing to commit)