views:

4349

answers:

6

This should be really simple. If I have a String like this:

../Test?/sample*.txt

then what is a generally-accepted way to get a list of files that match this pattern? (e.g. it should match ../Test1/sample22b.txt and ../Test4/sample-spiffy.txt but not ../Test3/sample2.blah or ../Test44/sample2.txt)

I've taken a look at org.apache.commons.io.filefilter.WildcardFileFilter and it seems like the right beast but I'm not sure how to use it for finding files in a relative directory path.

I suppose I can look the source for ant since it uses wildcard syntax, but I must be missing something pretty obvious here.

(edit: the above example was just a sample case. I'm looking for the way to parse general paths containing wildcards at runtime. I figured out how to do it based on mmyers' suggestion but it's kind of annoying. Not to mention that the java JRE seems to auto-parse simple wildcards in the main(String[] arguments) from a single argument to "save" me time and hassle... I'm just glad I didn't have non-file arguments in the mix.)

+1  A: 

The Apache filter is built for iterating files in a known directory. To allow wildcards in the directory also, you would have to split the path on '\' or '/' and do a filter on each part separately.

Michael Myers
This worked. It was a bit annoying, but not particularly trouble-prone. However, I do look forward to JDK7's features for glob matching.
Jason S
A: 

Why not use do something like:

File myRelativeDir = new File("../../foo");
String fullPath = myRelativeDir.getCanonicalPath();
Sting wildCard = fullPath + File.separator + "*.txt";

// now you have a fully qualified path

Then you won't have to worry about relative paths and can do your wildcarding as needed.

Elijah
Because the relative path can have wildcards as well.
Jason S
Oh, wait, I misunderstood.
Jason S
+2  A: 

Might not help you right now, but JKD7 is intended to have glob and regex file name matching as part of "More NIO Features".

Tom Hawtin - tackline
A: 

You could convert your wildcard string to a regular expression and use that with String's matches method. Following your example:

String original = "../Test?/sample*.txt";
String regex = original.replace("?", ".?").replace("*", ".*?");

This works for your examples:

Assert.assertTrue("../Test1/sample22b.txt".matches(regex));
Assert.assertTrue("../Test4/sample-spiffy.txt".matches(regex));

And counter-examples:

Assert.assertTrue(!"../Test3/sample2.blah".matches(regex));
Assert.assertTrue(!"../Test44/sample2.txt".matches(regex));
Fabian Steeg
+1  A: 

I usually use FileUtils from Apache commons-io (listFiles and iterateFiles methods). Usually the code looks something like this:

File dir = new File(".");
FileFilter fileFilter = new WildcardFileFilter("sample*.java");
File[] files = dir.listFiles(fileFilter);
for (int i = 0; i < files.length; i++) {
   System.out.println(files[i]);
}

To solve your issue with the TestX folders, I would first iterate through the list of folders:

File[] dirs = new File(".").listFiles(new WildcardFileFilter("Test*.java");
for (int i=0; i<dirs.length; i++) {
   File dir = dirs[i];
   if (dir.isDirectory()) {
       File[] files = dir.listFiles(new WildcardFileFilter("sample*.java"));
   }
}

Quite a 'brute force' solution but should work fine. If this doesn't fit your needs, you can always use the RegexFileFilter.

Vladimir
What part of FileUtils?
Michael Myers
Okay, now you've gotten to exactly where Jason S was when he posted the question.
Michael Myers
not quite. There's also the RegexFileFilter that can be used (but personally never had the need to do so).
Vladimir
+4  A: 

Consider DirectoryScanner from Apache Ant:

DirectoryScanner scanner = new DirectoryScanner();
scanner.setIncludes(new String[]{"**/*.java"});
scanner.setBasedir("C:/Temp");
scanner.setCaseSensitive(false);
scanner.scan();
String[] files = scanner.getIncludedFiles();

You'll need to reference ant.jar (~ 1.3 MB for ant 1.7.1).

Misha
ooh ahh! I'll have to try it. :)
Jason S