Search code examples
javarecursionsmbsmbj

Recursive file search for designated extension


I am using SMBClient to connect to my SMB server with Java.

How can I recursively scan my entire SMB share to get a listing of all files with an .mp4 extension?

This is my code that only scans the one designated directory:

private void btnFileCountActionPerformed(java.awt.event.ActionEvent evt) {
    SMBClient client = new SMBClient();
    try (Connection connection = client.connect("192.168.X.XXX")) {
        AuthenticationContext ac = new AuthenticationContext("[email protected]", "XXXXXX".toCharArray(), "Mastafin");
        Session session = connection.authenticate(ac);

        try (DiskShare share = (DiskShare) session.connectShare("Folder With Spaces")) {
            for (FileIdBothDirectoryInformation f : share.list("LOTS OF SUBDIRS TO SCAN", "*.mp4")) {
                System.out.println("File : " + f.getFileName());
            }
        } catch (Exception e) {
            System.out.println(e);
        }
    } catch (Exception e) {
        System.out.println(e);
    }
}

Solution

  • Here are some fairly straightforward tweaks to your code to get it to fill an ArrayList recursively. It isn't necessarily the most efficient way of doing this, as it gathers all filenames, and then throws away the ones that don't end with .mp4, but it should give you a straightforward place to start building from.

    private void btnFileCountActionPerformed(java.awt.event.ActionEvent evt) {
        try (SMBClient client = new SMBClient()) {
            try (Connection connection = client.connect(SERVER)) {
                AuthenticationContext ac = new AuthenticationContext(USERNAME, PASSWORD.toCharArray(), WORKGROUP);
                try (Session session = connection.authenticate(ac)) {
                    try (DiskShare share = (DiskShare) session.connectShare(SHARE)) {
                        List<String> files = new ArrayList<>();
                        listFiles(share, START_DIR, files);
                        files.removeIf(name -> !name.toLowerCase().endsWith(".mp4"));
                        files.forEach(System.out::println);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace(System.err);
        }
    }
    
    private void listFiles(DiskShare share, String path, Collection<String> files) {
        List<String> dirs = new ArrayList<>();
        String extPath = path.isEmpty() ? path : path + "\\";
        for (FileIdBothDirectoryInformation f : share.list(path)) {
            if ((f.getFileAttributes() & FileAttributes.FILE_ATTRIBUTE_DIRECTORY.getValue()) != 0) {
                if (!isSpecialDir(f.getFileName())) {
                    dirs.add(f.getFileName());
                }
            } else {
                files.add(extPath + f.getFileName());
            }
        }
        dirs.forEach(dir -> listFiles(share, extPath + dir, files));
    }
    
    private static boolean isSpecialDir(String fileName) {
        return fileName.equals(".") || fileName.equals("..");
    }