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

时间:2021-11-17 18:29:09

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)

那么,什么是一种普遍接受的获取与此模式匹配的文件列表的方法呢?(例如:it should match ./Test1/sample22b)。txt和. . / Test4 / sample-spiffy。txt但不是. . / Test3 / sample2。胡说或. . / 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.

我已经查看了org.apache.common . filefilter.wildcardfilefilter,它看起来是正确的,但我不确定如何使用它来查找相对目录路径中的文件。

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

我想我可以查找ant的源代码,因为它使用了通配符语法,但是我肯定遗漏了一些非常明显的东西。

(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.)

(编辑:上面的例子只是一个例子。我正在寻找在运行时解析包含通配符的一般路径的方法。我知道如何根据迈尔斯的建议去做,但这很烦人。更不用说,java JRE似乎从一个参数自动解析简单的通配符(String[]参数),以“节省”我的时间和麻烦……我很高兴我没有在混合中使用非文件参数。

15 个解决方案

#1


66  

Consider DirectoryScanner from Apache Ant:

考虑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();

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

你需要参考蚂蚁。jar (~ 1.3 MB,适用于ant 1.7.1)。

#2


106  

Try FileUtils from Apache commons-io (listFiles and iterateFiles methods):

尝试使用Apache commons-io (listFiles和iterateFiles方法)中的FileUtils:

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:

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

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

蛮力的解决办法,但应该没问题。如果这不符合您的需要,您可以一直使用RegexFileFilter。

#3


33  

Here are examples of listing files by pattern powered by Java 7 nio globbing and Java 8 lambdas:

下面是由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));
    }

or

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

#4


27  

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

#5


17  

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

现在可能对您没有帮助,但是JDK 7打算将glob和regex文件名称匹配作为“更多NIO特性”的一部分。

#6


12  

The wildcard library efficiently does both glob and regex filename matching:

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

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

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

The implementation is succinct -- JAR is only 12.9 kilobytes.

实现是简洁的——JAR只有12.9千字节。

#7


11  

Since Java 8 you can use Files#find method directly from java.nio.file.

因为Java 8可以直接从Java .nio.file中使用文件#find方法。

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

Example usage

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

#8


8  

Simple Way without using any external import is to use this method

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

I created csv files named with billing_201208.csv ,billing_201209.csv ,billing_201210.csv and it looks like working fine.

我创建了以billing_201208命名的csv文件。csv,billing_201209。csv,billing_201210。csv看起来不错。

Output will be the following if files listed above exists

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

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

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

#9


6  

As posted in another answer, the wildcard library works for both glob and regex filename matching: http://code.google.com/p/wildcard/

在另一个答案中,通配符库在glob和regex filename匹配上工作:http://code.google.com/p/wildcard/。

I used the following code to match glob patterns including absolute and relative on *nix style file systems:

我使用以下代码来匹配glob模式,包括绝对和相对的*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();

I spent some time trying to get the FileUtils.listFiles methods in the Apache commons io library (see Vladimir's answer) to do this but had no success (I realise now/think it can only handle pattern matching one directory or file at a time).

我花了一些时间试图获取FileUtils。在Apache commons io库中使用listFiles方法(参见Vladimir的答案),但是没有成功(我现在知道/认为它只能处理一个目录或文件的模式)。

Additionally, using regex filters (see F*'s answer) for processing arbitrary user supplied absolute type glob patterns without searching the entire file system would require some preprocessing of the supplied glob to determine the largest non-regex/glob prefix.

另外,使用regex过滤器(参见F*的答案)来处理任意用户提供的绝对类型的glob模式,而无需搜索整个文件系统,就需要对提供的glob进行一些预处理,以确定最大的非regex/glob前缀。

Of course, Java 7 may handle the requested functionality nicely, but unfortunately I'm stuck with Java 6 for now. The library is relatively minuscule at 13.5kb in size.

当然,Java 7可以很好地处理请求的功能,但不幸的是,我现在还不能适应Java 6。该库的规模相对较小,为13.5kb。

Note to the reviewers: I attempted to add the above to the existing answer mentioning this library but the edit was rejected. I don't have enough rep to add this as a comment either. Isn't there a better way...

注意到审稿人:我试图将上面的内容添加到这个库中,但是编辑被拒绝了。我没有足够的代表来添加这个评论。有没有更好的办法……

#10


5  

You should be able to use the WildcardFileFilter. Just use System.getProperty("user.dir") to get the working directory. Try this:

您应该能够使用WildcardFileFilter。使用System.getProperty(“user.dir”)来获取工作目录。试试这个:

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

You should not need to replace * with [.*], assuming wildcard filter uses java.regex.Pattern. I have not tested this, but I do use patterns and file filters constantly.

你不应该用[。,假设通配符过滤器使用java.regex.Pattern。我没有测试过这个,但是我经常使用模式和文件过滤器。

#11


4  

Glob of Java7: Finding Files. (Sample)

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

#12


3  

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.

Apache过滤器是为在已知目录中迭代文件而构建的。若要在目录中允许通配符,则必须在“\”或“/”上分割路径,并分别对每个部分进行筛选。

#13


0  

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.

这样,您就不必担心相对路径了,并且可以根据需要执行通配符。

#14


0  

Implement the JDK FileVisitor interface. Here is an example http://wilddiary.com/list-files-matching-a-naming-pattern-java/

实现JDK FileVisitor接口。这里有一个示例:http://wilddiary.com/list- files-matchinga-naming-pattern -java/。

#15


0  

Util Method:

实效的方法:

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

    }

jUnit Test:

jUnit测试:

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

Output:

输出:

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

#1


66  

Consider DirectoryScanner from Apache Ant:

考虑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();

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

你需要参考蚂蚁。jar (~ 1.3 MB,适用于ant 1.7.1)。

#2


106  

Try FileUtils from Apache commons-io (listFiles and iterateFiles methods):

尝试使用Apache commons-io (listFiles和iterateFiles方法)中的FileUtils:

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:

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

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

蛮力的解决办法,但应该没问题。如果这不符合您的需要,您可以一直使用RegexFileFilter。

#3


33  

Here are examples of listing files by pattern powered by Java 7 nio globbing and Java 8 lambdas:

下面是由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));
    }

or

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

#4


27  

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

#5


17  

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

现在可能对您没有帮助,但是JDK 7打算将glob和regex文件名称匹配作为“更多NIO特性”的一部分。

#6


12  

The wildcard library efficiently does both glob and regex filename matching:

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

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

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

The implementation is succinct -- JAR is only 12.9 kilobytes.

实现是简洁的——JAR只有12.9千字节。

#7


11  

Since Java 8 you can use Files#find method directly from java.nio.file.

因为Java 8可以直接从Java .nio.file中使用文件#find方法。

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

Example usage

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

#8


8  

Simple Way without using any external import is to use this method

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

I created csv files named with billing_201208.csv ,billing_201209.csv ,billing_201210.csv and it looks like working fine.

我创建了以billing_201208命名的csv文件。csv,billing_201209。csv,billing_201210。csv看起来不错。

Output will be the following if files listed above exists

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

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

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

#9


6  

As posted in another answer, the wildcard library works for both glob and regex filename matching: http://code.google.com/p/wildcard/

在另一个答案中,通配符库在glob和regex filename匹配上工作:http://code.google.com/p/wildcard/。

I used the following code to match glob patterns including absolute and relative on *nix style file systems:

我使用以下代码来匹配glob模式,包括绝对和相对的*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();

I spent some time trying to get the FileUtils.listFiles methods in the Apache commons io library (see Vladimir's answer) to do this but had no success (I realise now/think it can only handle pattern matching one directory or file at a time).

我花了一些时间试图获取FileUtils。在Apache commons io库中使用listFiles方法(参见Vladimir的答案),但是没有成功(我现在知道/认为它只能处理一个目录或文件的模式)。

Additionally, using regex filters (see F*'s answer) for processing arbitrary user supplied absolute type glob patterns without searching the entire file system would require some preprocessing of the supplied glob to determine the largest non-regex/glob prefix.

另外,使用regex过滤器(参见F*的答案)来处理任意用户提供的绝对类型的glob模式,而无需搜索整个文件系统,就需要对提供的glob进行一些预处理,以确定最大的非regex/glob前缀。

Of course, Java 7 may handle the requested functionality nicely, but unfortunately I'm stuck with Java 6 for now. The library is relatively minuscule at 13.5kb in size.

当然,Java 7可以很好地处理请求的功能,但不幸的是,我现在还不能适应Java 6。该库的规模相对较小,为13.5kb。

Note to the reviewers: I attempted to add the above to the existing answer mentioning this library but the edit was rejected. I don't have enough rep to add this as a comment either. Isn't there a better way...

注意到审稿人:我试图将上面的内容添加到这个库中,但是编辑被拒绝了。我没有足够的代表来添加这个评论。有没有更好的办法……

#10


5  

You should be able to use the WildcardFileFilter. Just use System.getProperty("user.dir") to get the working directory. Try this:

您应该能够使用WildcardFileFilter。使用System.getProperty(“user.dir”)来获取工作目录。试试这个:

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

You should not need to replace * with [.*], assuming wildcard filter uses java.regex.Pattern. I have not tested this, but I do use patterns and file filters constantly.

你不应该用[。,假设通配符过滤器使用java.regex.Pattern。我没有测试过这个,但是我经常使用模式和文件过滤器。

#11


4  

Glob of Java7: Finding Files. (Sample)

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

#12


3  

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.

Apache过滤器是为在已知目录中迭代文件而构建的。若要在目录中允许通配符,则必须在“\”或“/”上分割路径,并分别对每个部分进行筛选。

#13


0  

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.

这样,您就不必担心相对路径了,并且可以根据需要执行通配符。

#14


0  

Implement the JDK FileVisitor interface. Here is an example http://wilddiary.com/list-files-matching-a-naming-pattern-java/

实现JDK FileVisitor接口。这里有一个示例:http://wilddiary.com/list- files-matchinga-naming-pattern -java/。

#15


0  

Util Method:

实效的方法:

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

    }

jUnit Test:

jUnit测试:

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

Output:

输出:

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