如何在Java中查找匹配通配符string的文件?

这应该很简单。 如果我有这样一个string:

../Test?/sample*.txt 

那么什么是普遍接受的方式来获得匹配这种模式的文件列表? (例如它应该匹配../Test1/sample22b.txt../Test4/sample-spiffy.txt但不是../Test3/sample2.blah../Test44/sample2.txt

我已经看了org.apache.commons.io.filefilter.WildcardFileFilter ,它似乎是正确的野兽,但我不知道如何使用它来查找相对目录path中的文件。

我想我可以看ant的源代码,因为它使用通配符语法,但我必须在这里丢失一些非常明显的东西。

编辑 :上面的例子只是一个示例,我正在寻找在运行时parsing包含通配符的通用path的方法,我根据mmyers的build议想出了办法,但这样做很烦人,更不用说了java JRE似乎从一个参数中自动parsingmain(String []参数)中的简单通配符来“保存”我的时间和麻烦…我很高兴我没有非文件参数混合。)

考虑Apache Ant中的DirectoryScanner:

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

你需要引用ant.jar(ant 1.7.1〜1.3 MB)。

我通常使用Apache commons-io ( iterateFilesiterateFiles方法)中的iterateFiles 。 通常代码看起来像这样 :

 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]); } 

为了解决TestX文件夹的问题,我将首先遍历文件夹列表:

 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")); } } 

相当“蛮力”的解决scheme,但应该正常工作。 如果这不符合您的需求,您可以随时使用RegexFileFilter 。

您可以将通配符string转换为正则expression式,并将其用于String的matches方法。 遵循你的例子:

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

这适用于你的例子:

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

反例:

 Assert.assertTrue(!"../Test3/sample2.blah".matches(regex)); Assert.assertTrue(!"../Test44/sample2.txt".matches(regex)); 

下面是按照Java 7 nio globbing和Java 8 lambdas的模式列出文件的示例:

  try (DirectoryStream<Path> dirStream = Files.newDirectoryStream( Paths.get(".."), "Test?/sample*.txt")) { dirStream.forEach(path -> System.out.println(path)); } 

要么

  PathMatcher pathMatcher = FileSystems.getDefault() .getPathMatcher("regex:Test.[\\/]sample\\w+\\.txt"); try (DirectoryStream<Path> dirStream = Files.newDirectoryStream( new File("..").toPath(), pathMatcher::matches)) { dirStream.forEach(path -> System.out.println(path)); } 

现在可能不会帮你,但是JDK 7打算把glob和regex文件名匹配成“更多NIO特性”的一部分。

通配符库有效地执行glob和regex文件名匹配:

http://code.google.com/p/wildcard/

实现简洁 – JAR只有12.9千字节。

从Java 8开始,您可以直接从java.nio.file使用Files#find方法。

 public static Stream<Path> find(Path start, int maxDepth, BiPredicate<Path, BasicFileAttributes> matcher, FileVisitOption... options) 

用法示例

 Files.find(startingPath, Integer.MAX_VALUE, (path, basicFileAttributes) -> path.toFile().getName().matches(".*.pom") ); 

不使用任何外部input的简单方法就是使用这种方法

我创build了以billing_201208.csv,billing_201209.csv,billing_201210.csv命名的csv文件,它看起来像正常工作。

如果上面列出的文件存在,则输出将如下所示

 found billing_201208.csv found billing_201209.csv found billing_201210.csv 

     //使用导入 - >导入java.io.File
         public static void main(String [] args){
        stringpathToScan =“。”;
        stringtarget_file;  // fileThatYouWantToFilter
         File folderToScan = new File(pathToScan); 
  File[] listOfFiles = folderToScan.listFiles(); for (int i = 0; i < listOfFiles.length; i++) { if (listOfFiles[i].isFile()) { target_file = listOfFiles[i].getName(); if (target_file.startsWith("billing") && target_file.endsWith(".csv")) { //You can add these files to fileList by using "list.add" here System.out.println("found" + " " + target_file); } } } } 

正如另一个答案中发布的,通配符库适用于glob和regex文件名匹配: http : //code.google.com/p/wildcard/

我使用下面的代码来匹配全局模式,包括绝对的和相对的* nix风格的文件系统:

 String filePattern = String baseDir = "./"; // If absolute path. TODO handle windows absolute path? if (filePattern.charAt(0) == File.separatorChar) { baseDir = File.separator; filePattern = filePattern.substring(1); } Paths paths = new Paths(baseDir, filePattern); List files = paths.getFiles(); 

我花了一些时间来尝试获取Apache Commons io库中的FileUtils.listFiles方法(请参阅Vladimir的答案),但没有成功(我现在意识到/认为它一次只能处理与一个目录或文件匹配的模式) 。

此外,使用正则expression式filter(参见Fabian的答案)来处理任意用户提供的绝对types全局模式而不search整个文件系统将需要对提供的全局文件进行一些预处理,以确定最大的非正则expression式/全局前缀。

当然,Java 7可以很好地处理所请求的function,但不幸的是,我现在仍然坚持使用Java 6。 图书馆的规模相对较小,只有13.5kb。

给审稿人的提示:我试图把上面的内容添加到提到这个图书馆的现有答案中,但是编辑被拒绝了。 我没有足够的代表添加此作为评论要么。 没有更好的方法

你应该能够使用WildcardFileFilter 。 只需使用System.getProperty("user.dir")来获取工作目录。 尝试这个:

 public static void main(String[] args) { File[] files = (new File(System.getProperty("user.dir"))).listFiles(new WildcardFileFilter(args)); //... } 

你不应该用[.*]replace* ,假设通配符filter使用java.regex.Pattern 。 我没有testing过这个,但是我经常使用模式和文件filter。

构buildApachefilter用于在已知目录中迭代文件。 要允许目录中的通配符也必须在“ \ ”或“ / ”上分开path,并对每个部分分别进行过滤。

Java7的Glob : 查找文件 。 ( 样品 )

为什么不使用做类似的事情:

 File myRelativeDir = new File("../../foo"); String fullPath = myRelativeDir.getCanonicalPath(); Sting wildCard = fullPath + File.separator + "*.txt"; // now you have a fully qualified path 

那么你不必担心相对path,可以根据需要做通配符。

实现JDK FileVisitor接口。 这是一个例子http://wilddiary.com/list-files-matching-a-naming-pattern-java/

使用方法:

 public static boolean isFileMatchTargetFilePattern(final File f, final String targetPattern) { String regex = targetPattern.replace(".", "\\."); //escape the dot first regex = regex.replace("?", ".?").replace("*", ".*"); return f.getName().matches(regex); } 

jUnittesting:

 @Test public void testIsFileMatchTargetFilePattern() { String dir = "D:\\repository\\org\my\\modules\\mobile\\mobile-web\\b1605.0.1"; String[] regexPatterns = new String[] {"_*.repositories", "*.pom", "*-b1605.0.1*","*-b1605.0.1", "mobile*"}; File fDir = new File(dir); File[] files = fDir.listFiles(); for (String regexPattern : regexPatterns) { System.out.println("match pattern [" + regexPattern + "]:"); for (File file : files) { System.out.println("\t" + file.getName() + " matches:" + FileUtils.isFileMatchTargetFilePattern(file, regexPattern)); } } } 

输出:

 match pattern [_*.repositories]: mobile-web-b1605.0.1.pom matches:false mobile-web-b1605.0.1.war matches:false _remote.repositories matches:true match pattern [*.pom]: mobile-web-b1605.0.1.pom matches:true mobile-web-b1605.0.1.war matches:false _remote.repositories matches:false match pattern [*-b1605.0.1*]: mobile-web-b1605.0.1.pom matches:true mobile-web-b1605.0.1.war matches:true _remote.repositories matches:false match pattern [*-b1605.0.1]: mobile-web-b1605.0.1.pom matches:false mobile-web-b1605.0.1.war matches:false _remote.repositories matches:false match pattern [mobile*]: mobile-web-b1605.0.1.pom matches:true mobile-web-b1605.0.1.war matches:true _remote.repositories matches:false