In order to get all files contained in a specified directory and according to some extensions, I'm using the method listFiles
of class FileUtils
from Apache Commons IO library, as in the following code sample.
ArrayList<String> wildcards = new ArrayList<>();
wildcards.add("*.cpp");
wildcards.add("*.h");
wildcards.add("*.txt");
File dir = new File("/path/to/dir");
Collection<File> found = FileUtils.listFiles(
dir,
new WildcardFileFilter(wildcards, IOCase.SENSITIVE),
DirectoryFileFilter.DIRECTORY);
List<File> files = new ArrayList<>(found);
The order of items in the resulting Collection<File>
varies in the different operating systems, so I would sort them (ie. the wrapping list files
) in according to the following rules.
Example:
/path/to/dir/first/subpath/main.cpp
/path/to/dir/first/subpath/utils.cpp
/path/to/dir/first/subpath/utils.h
/path/to/dir/first/main.cpp
/path/to/dir/first/utils.cpp
/path/to/dir/first/utils.h
/path/to/dir/second/main.cpp
/path/to/dir/second/utils.cpp
/path/to/dir/second/utils.h
/path/to/dir/README.txt
os. listdir() method gets the list of all files and directories in a specified directory. By default, it is the current directory.
After an entire afternoon of scratching my head at this, here's what worked for me:
files.sort((p1, p2) -> pathToStr(p1).compareToIgnoreCase(pathToStr(p2)));
files.forEach(System.out::println); //They'll be ordered now!
//A method I wrote for pulling this off
public static String pathToStr(File path) {
boolean isDir = path.isDirectory();
String str = path.getAbsolutePath().replace("\\", "/").replace("/", "/\0");
if (!isDir) {
int idx = str.lastIndexOf("/\0");
str = str.substring(0, idx) + str.substring(idx, str.length()).replace("/\0", "/");
}
return str;
}
So basically, what pathToStr()
does is making a string representation of a file path, but with a twist: all folder names in the path will have a null \0
character prepended. This way, the stock string ordering will push all subfolders to the top of each folder. It should work fine as long as you don't have any file names starting with a null char, which I don't think is even possible due to how good old C handles strings.
As an additional note, if you want to order things in a more Unix-like fashion, you can change that compareToIgnoreCase
to just compareTo
, in order to consider different casing.
This question may be kind of old (5 years old at the moment I'm writing this), but I couldn't find any answers that would not involve using libraries or mixing several comparators, so once I figured it out I decided to come back here and add my two cents. Enjoy your saved afternoon.
Edit: Since the question does not use NIO paths, I had to change my code to an alternative version using only File
; but in case you're using NIO paths like me, here's the code I'm using:
List<Path> items = Files.walk(rootFolder).collect(Collectors.toList());
items.sort((p1, p2) -> pathToStr(p1).compareToIgnoreCase(pathToStr(p2)));
items.forEach(System.out::println); //They'll be ordered now!
public static String pathToStr(Path path) {
boolean isDir = Files.isDirectory(path, LinkOption.NOFOLLOW_LINKS);
String str = path.toAbsolutePath().toString().replace("\\", "/").replace("/", "/\0");
if (!isDir) {
int idx = str.lastIndexOf("/\0");
str = str.substring(0, idx) + str.substring(idx, str.length()).replace("/\0", "/");
}
return str;
}
There we go, whether you're using NIO or not, this answer has you covered.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With