如何在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 ( iterateFiles
和iterateFiles
方法)中的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特性”的一部分。
从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