Isso deve ser realmente simples. Se eu tiver uma String como esta:
../Test?/sample*.txt
então, qual é a maneira geralmente aceita de obter uma lista de arquivos que correspondem a esse padrão? (por exemplo, deve corresponder ../Test1/sample22b.txt
e ../Test4/sample-spiffy.txt
mas não ../Test3/sample2.blah
ou ../Test44/sample2.txt
)
Dei uma olhada org.apache.commons.io.filefilter.WildcardFileFilter
e parece a besta certa, mas não sei como usá-la para encontrar arquivos em um caminho de diretório relativo.
Suponho que posso procurar na fonte o form, pois ele usa sintaxe curinga, mas devo estar perdendo algo bastante óbvio aqui.
( edit : o exemplo acima era apenas um exemplo de caso. Estou procurando uma maneira de analisar caminhos gerais que contêm curingas em tempo de execução. Eu descobri como fazê-lo com base na sugestão de mmyers, mas é meio irritante. Sem mencionar que o JRE java parece analisar automaticamente curingas simples nos argumentos principais (String []) de um único argumento para "economizar" tempo e aborrecimentos ... Estou feliz por não ter argumentos que não sejam de arquivo misturar.)
Respostas:
Considere o DirectoryScanner do Apache Ant:
Você precisará fazer referência ao ant.jar (~ 1,3 MB para o ant 1.7.1).
fonte
DirectoryScanner
é encontrado no plexus-utils (241Kb). Qual é menor entãoant.jar
(1.9Mb).ls
com o mesmo padrão de arquivo (milissegundos usandols <pattern>
minutos vs. ao usar o DirectoryScanner) ...Tente
FileUtils
no Apache commons-io (listFiles
eiterateFiles
métodos):Para resolver seu problema com as
TestX
pastas, primeiro eu iria percorrer a lista de pastas:Bastante uma solução de 'força bruta', mas deve funcionar bem. Se isso não atender às suas necessidades, você sempre poderá usar o RegexFileFilter .
fonte
A seguir, exemplos de listagem de arquivos por padrão com tecnologia Java 7 nio globbing e Java 8 lambdas:
ou
fonte
Files.walk(Paths.get("..")).filter(matcher::matches).forEach(System.out::println);
Você pode converter sua string curinga em uma expressão regular e usá-la com o
matches
método String . Seguindo o seu exemplo:Isso funciona para seus exemplos:
E contra-exemplos:
fonte
?
public boolean estático isFileMatchTargetFilePattern (arquivo final f, final String targetPattern) {`` String regex = targetPattern.replace (".", "\\."); `regex = regex.replace("?", ".?").replace("
*", ".
*");
return f.getName().matches(regex);
}
StringBuffer regexBuffer = ...; Matcher matcher = Pattern.compile("(.*?)([*?])").matcher(original); while (matcher.find()) { matcher.appendReplacement(regexBuffer, (Pattern.quote(matcher.group(1)) + (matcher.group(2).equals("*") ? ".*?" : ".?")).replace("\\", "\\\\").replace("$", "\\$")); } matcher.appendTail(regexBuffer);
.
vez de.?
.Desde o Java 8, você pode usar o
Files#find
método diretamente dejava.nio.file
.Exemplo de uso
fonte
Pode não ajudar você agora, mas o JDK 7 deve ter o nome de arquivo glob e regex correspondente como parte de "Mais recursos da NIO".
fonte
A biblioteca curinga efetivamente faz a correspondência dos nomes de arquivo glob e regex:
http://code.google.com/p/wildcard/
A implementação é sucinta - o JAR é de apenas 12,9 kilobytes.
fonte
A maneira simples, sem usar nenhuma importação externa, é usar esse método
Criei arquivos csv nomeados com billing_201208.csv, billing_201209.csv, billing_201210.csv e parece que está funcionando bem.
A saída será a seguinte se os arquivos listados acima existirem
fonte
Conforme publicado em outra resposta, a biblioteca curinga funciona para correspondência de nome de arquivo glob e regex: http://code.google.com/p/wildcard/
Usei o código a seguir para corresponder aos padrões globais, incluindo absoluto e relativo nos sistemas de arquivos no estilo * nix:
Passei algum tempo tentando obter os métodos FileUtils.listFiles na biblioteca do Apache commons io (consulte a resposta de Vladimir) para fazer isso, mas não tive sucesso (eu percebo agora / acho que ele só pode lidar com padrões que correspondem a um diretório ou arquivo por vez) .
Além disso, o uso de filtros regex (consulte a resposta de Fabian) para processar padrões glob globais do tipo arbitrário fornecidos pelo usuário sem pesquisar em todo o sistema de arquivos exigiria algum pré-processamento da glob fornecida para determinar o maior prefixo não-regex / glob.
Obviamente, o Java 7 pode lidar bem com a funcionalidade solicitada, mas infelizmente estou preso ao Java 6 por enquanto. A biblioteca é relativamente minúscula, com 13,5 kb de tamanho.
Nota para os revisores: tentei adicionar o acima à resposta existente mencionando esta biblioteca, mas a edição foi rejeitada. Também não tenho representante suficiente para adicionar isso como comentário. Não existe uma maneira melhor ...
fonte
Você deve poder usar o
WildcardFileFilter
. Basta usarSystem.getProperty("user.dir")
para obter o diretório de trabalho. Tente o seguinte:Você não deve precisar substituir
*
com[.*]
, assumindo usos do filtro curingajava.regex.Pattern
. Não testei isso, mas uso padrões e filtros de arquivo constantemente.fonte
Glob de Java7: Localizando arquivos . ( Amostra )
fonte
O filtro Apache foi criado para iterar arquivos em um diretório conhecido. Para permitir curingas no diretório também, você teria que dividir o caminho em '
\
' ou '/
' e fazer um filtro em cada parte separadamente.fonte
Por que não usar faça algo como:
Então você não precisará se preocupar com caminhos relativos e poderá fazer seu curinga conforme necessário.
fonte
Implemente a interface do JDK FileVisitor. Aqui está um exemplo http://wilddiary.com/list-files-matching-a-naming-pattern-java/
fonte
Método Util:
Teste jUnit:
Resultado:
fonte
foo/bar.txt
correspondefoo?bar.txt
e isso não é correto../Test?/sample*.txt
fonte