如何使用Apache FileFilterUtils排除特定文件?

时间:2014-11-11 13:13:34

标签: java apache file filter copy

请考虑以下文件夹结构:

src
  |_text1.txt
  |_text2.txt
  |_content
      |_text1.txt
      |_text2.txt

如何设计 org.apache.commons.io.filefilter.IOFileFilter 以排除 src / text1.txt src / text2 .txt 但保留 src / content / text1.txt src / content / text2.txt

目前我的过滤器如下所示:

IOFileFilter filter = FileFilterUtils.and(
                    FileFilterUtils.notFileFilter(FileFilterUtils.nameFileFilter("text1.txt", IOCase.SENSITIVE)),
                    FileFilterUtils.notFileFilter(FileFilterUtils.nameFileFilter("text2.txt", IOCase.SENSITIVE))
            );
FileUtils.copyDirectory(new File("src"), new File("dst"), filter);

但上面的代码片段显然不会复制 src / content / 文件夹中的两个文本文件(我想复制它)...顺便说一句。 可更改文本文件的名称。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

AFAIK commons io没有提供像PathFileFilter这样的东西,因此你必须在这里添加你自己的过滤器。

NameFileFilter,顾名思义,只检查文件名,即路径不相关。

提供自己的过滤器不应该那么难。我建议在此处对AbstractFileFilterNameFileFilter进行子类化。子类化NameFileFilter可能被认为是一种有点肮脏的方法,因为您不仅要检查名称,还要求您覆盖accept()方法:

public boolean accept(File file) {
   return accept( file.getPath() );
}

public boolean accept(File dir, String name) {
  //use normalize to account for possible double separators or windows paths which use \
  return accept( FilenameUtils.normalize( dir.getPath() + "/" + name ) );
}

protected boolean accept( String path ) {     
   for (String nameSuffix: names) {
     if (caseSensitivity.checkEndsWith( path, nameSuffix )) {
         return true;
     }
   }
   return false;
}

然后你就像FileFilterUtils.notFileFilter(new PathFileFilter("/text1.txt"))等一样使用它。

或者,您可以提供一组模式并检查它们:

private Set<Pattern> pathPatterns = new HashSet<>();

PathFileFilter(String... patterns) {
   for( String p : patterns ) {
     pathPatterns.add( Pattern.compile(p) );
   }
}

protected boolean accept( String path ) {     
  for (Pattern pattern : pathPatterns) {
    //separatorsToUnix is used to convert \ to /
    if ( pattern.matches( FilenameUtils.separatorsToUnix( path ) )) {
      return true;
    }
  }
  return false;
}

用法:new PathFileFilter("(?i)(.*/)?test[12]\\.txt");new PathFileFilter("(?i)(.*/)?test1\\.txt", "(?i)(.*/)?anothertest2\\.txt");

正则表达式的简短细分:

  • (?i)使表达式不区分大小写,将其留作区分大小写的匹配
  • (.*/)?表示如果文件名前面有任何内容,则必须以斜杠结尾,即匹配some/path/test1.txt但不匹配someothertest1.txt
  • test[12]\\.txt将是文件名,此处为text,后跟12,最后为.txt