如何在Java中查找与通配符字符串匹配的文件?

Jas*_*n S 144 java file wildcard

这应该很简单.如果我有这样的字符串:

../Test?/sample*.txt
Run Code Online (Sandbox Code Playgroud)

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

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

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

(编辑:上面的例子只是一个示例案例.我正在寻找在运行时解析包含通配符的常规路径的方法.我根据mmyers的建议想出了如何做到这一点,但这有点烦人.更不用说java JRE似乎从一个参数中自动解析main(String []参数)中的简单通配符,以"节省"我的时间和麻烦......我很高兴我没有非文件参数混合.)

Vla*_*mir 116

尝试FileUtils使用Apache commons-io(listFilesiterateFiles方法):

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]);
}
Run Code Online (Sandbox Code Playgroud)

要解决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"));
   }
}
Run Code Online (Sandbox Code Playgroud)

相当"蛮力"的解决方案,但应该工作正常.如果这不符合您的需求,您可以随时使用RegexFileFilter.

  • 好的,现在您已经准确了解了 Jason S 发布问题时的位置。 (2认同)

Mis*_*sha 74

考虑来自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();
Run Code Online (Sandbox Code Playgroud)

你需要引用ant.jar(对于ant 1.7.1,大约1.3 MB).

  • @Moreaki 作为单独的答案,而不是评论 (2认同)

Vad*_*zim 49

以下是按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));
    }
Run Code Online (Sandbox Code Playgroud)

要么

    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));
    }
Run Code Online (Sandbox Code Playgroud)

  • 或者`Files.walk(Paths.get("..")).filter(matcher :: matches).forEach(System.out :: println);` (9认同)

Fab*_*eeg 28

您可以将通配符字符串转换为正则表达式,并将其与String的matches方法一起使用.按照你的例子:

String original = "../Test?/sample*.txt";
String regex = original.replace("?", ".?").replace("*", ".*?");
Run Code Online (Sandbox Code Playgroud)

这适用于您的示例:

Assert.assertTrue("../Test1/sample22b.txt".matches(regex));
Assert.assertTrue("../Test4/sample-spiffy.txt".matches(regex));
Run Code Online (Sandbox Code Playgroud)

反例:

Assert.assertTrue(!"../Test3/sample2.blah".matches(regex));
Assert.assertTrue(!"../Test44/sample2.txt".matches(regex));
Run Code Online (Sandbox Code Playgroud)

  • 这不适用于包含特殊正则表达式字符的文件,如(,+或$) (3认同)
  • 为什么用'.*?`替换*?`public static boolean isFileMatchTargetFilePattern(final File f,final String targetPattern){``String regex = targetPattern.replace(".","\\.");``regex = regex.replace("?",".?? ").replace("`*`",".`*`"); ``return f.getName().matches(regex);``}` (2认同)

Grz*_*jos 19

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

public static Stream<Path> find(Path start,
                                int maxDepth,
                                BiPredicate<Path, BasicFileAttributes> matcher,
                                FileVisitOption... options)
Run Code Online (Sandbox Code Playgroud)

用法示例

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

  • 您能否扩展该示例以打印流中保存的第一个匹配项的路径? (2认同)
  • 恕我直言,这是 2022 年最简单的解决方案。不需要外部库,并且可以通过 lambda 方法编写任何条件。谢谢! (2认同)

Tom*_*ine 18

可能现在没有帮助,但JDK 7旨在将glob和正则表达式文件名匹配为"更多NIO功能"的一部分.

  • 在Java 7中:Files.newDirectoryStream(path,glob-pattern) (3认同)

Nat*_*teS 12

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

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

实施简洁 - JAR只有12.9千字节.

  • 这是OSS,继续把它放在Maven Central上.:) (3认同)
  • 唯一的缺点是它不在Maven Central中 (2认同)

Uma*_*ziz 10

不使用任何外部导入的简单方法是使用此方法

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

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

found billing_201208.csv
found billing_201209.csv
found billing_201210.csv
Run Code Online (Sandbox Code Playgroud)

    //Use Import ->import java.io.File
        public static void main(String[] args) {
        String pathToScan = ".";
        String target_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); 
                }
           }
     }    
}
Run Code Online (Sandbox Code Playgroud)


Oli*_*man 6

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

我使用以下代码来匹配*nix样式文件系统上的包括绝对和相对的glob模式:

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();
Run Code Online (Sandbox Code Playgroud)

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

此外,使用正则表达式过滤器(参见Fabian的答案)处理任意用户提供的绝对类型glob模式而不搜索整个文件系统将需要对提供的glob进行一些预处理以确定最大的非正则表达式/ glob前缀.

当然,Java 7可以很好地处理所请求的功能,但遗憾的是我现在仍然坚持使用Java 6.该库相当小,尺寸为13.5kb.

评论者注意:我试图将上述内容添加到提及此库的现有答案中,但编辑被拒绝.我没有足够的代表将其添加为评论.是不是有更好的方法......


小智 5

你应该可以使用WildcardFileFilter.只是System.getProperty("user.dir")用来获取工作目录.试试这个:

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

你不应该需要更换*[.*]假设通配符过滤器的用途java.regex.Pattern.我没有测试过这个,但我确实经常使用模式和文件过滤器.