这应该很简单。如果我有这样的字符串:
../Test?/sample*.txt
那么获得与此模式匹配的文件列表的普遍接受的方法是什么? (例如,它应与../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 []参数)中的简单通配符,以“节省”我的时间和麻烦......我很高兴我混合中没有非文件参数。)
答案 0 :(得分:113)
从FileUtils
(listFiles
和iterateFiles
方法)尝试Apache commons-io:
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"));
}
}
相当'蛮力'的解决方案,但应该工作正常。如果这不符合您的需求,您可以随时使用RegexFileFilter。
答案 1 :(得分:70)
考虑来自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)。
答案 2 :(得分:43)
以下是按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));
}
答案 3 :(得分:27)
您可以将通配符字符串转换为正则表达式,并将其与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));
答案 4 :(得分:17)
现在可能没有帮助,但JDK 7的目的是将glob和regex文件名匹配为“更多NIO功能”的一部分。
答案 5 :(得分:16)
从Java 8开始,您可以直接从Files#find
使用java.nio.file
方法。
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")
);
答案 6 :(得分:12)
答案 7 :(得分:10)
不使用任何外部导入的简单方法是使用此方法
我创建了以billing_201208.csv,billing_201209.csv,billing_201210.csv命名的csv文件,看起来工作正常。
如果上面列出的文件存在,则输出如下
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); } } } }
答案 8 :(得分: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();
我花了一些时间尝试在Apache commons io库中获取FileUtils.listFiles方法(参见Vladimir的回答)来做这个但没有成功(我现在意识到/认为它只能处理一个目录或文件的模式匹配一次)。
此外,使用正则表达式过滤器(请参阅Fabian的答案)处理任意用户提供的绝对类型glob模式而不搜索整个文件系统将需要对提供的glob进行一些预处理以确定最大的非正则表达式/ glob前缀。
当然,Java 7可以很好地处理所请求的功能,但不幸的是我现在仍然坚持使用Java 6。该库的大小相当微小,为13.5kb。
评论者注意:我试图将上述内容添加到提及此库的现有答案中,但编辑被拒绝。我没有足够的代表将其添加为评论。没有更好的方法......
答案 9 :(得分:5)
您应该可以使用WildcardFileFilter
。只需使用System.getProperty("user.dir")
即可获取工作目录。试试这个:
public static void main(String[] args) {
File[] files = (new File(System.getProperty("user.dir"))).listFiles(new WildcardFileFilter(args));
//...
}
假设通配符过滤器使用*
,您不需要将[.*]
替换为java.regex.Pattern
。我没有对此进行过测试,但我确实不断使用模式和文件过滤器。
答案 10 :(得分:4)
答案 11 :(得分:3)
Apache过滤器用于迭代已知目录中的文件。要同时允许目录中的通配符,您必须在“\
”或“/
”上拆分路径,并分别对每个部分进行过滤。
答案 12 :(得分:0)
为什么不使用类似的东西:
File myRelativeDir = new File("../../foo");
String fullPath = myRelativeDir.getCanonicalPath();
Sting wildCard = fullPath + File.separator + "*.txt";
// now you have a fully qualified path
然后你不必担心相对路径,可以根据需要进行通配。
答案 13 :(得分:0)
Path testPath = Paths.get("C:\");
Stream<Path> stream =
Files.find(testPath, 1,
(path, basicFileAttributes) -> {
File file = path.toFile();
return file.getName().endsWith(".java");
});
// Print all files found
stream.forEach(System.out::println);
答案 14 :(得分:0)
Util方法:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class UserAuthorizationAttribute : Attribute, IAuthorizationFilter
{
public void OnAuthorization(Microsoft.AspNet.Mvc.Filters.AuthorizationContext filterContext)
{
filterContext.Controller.ViewData["IdentityUser"] = filterContext.HttpContext.User;
}
}
jUnit测试:
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);
}
输出:
@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));
}
}
}
答案 15 :(得分:0)
实现JDK FileVisitor接口。以下是http://wilddiary.com/list-files-matching-a-naming-pattern-java/
的示例答案 16 :(得分:-1)
使用 io 库的 File 类的最简单易行的方法是:
String startingdir="The directory name";
String filenameprefix="The file pattern"
File startingDirFile=new File(startingdir);
final File[] listFiles=startingDirFile.listFiles(new FilenameFilter() {
public boolean accept(File arg0,String arg1)
{System.out.println(arg0+arg1);
return arg1.matches(filenameprefix);}
});
System.out.println(Arrays.toString(listFiles));