我有以下目录结构:
/path/to/stuff/org/foo/bar/
/path/to/stuff/org/foo/bar/1.2.3/
/path/to/stuff/org/foo/bar/1.2.3/myfile.ext
/path/to/stuff/org/foo/bar/1.2.4/
/path/to/stuff/org/foo/bar/1.2.4/myfile.ext
/path/to/stuff/org/foo/bar/blah/
/path/to/stuff/org/foo/bar/blah/2.1/
/path/to/stuff/org/foo/bar/blah/2.1/myfile.ext
/path/to/stuff/org/foo/bar/blah/2.2/
/path/to/stuff/org/foo/bar/blah/2.2/myfile.ext
我想得到以下输出:
/path/to/stuff/org/foo/bar/
/path/to/stuff/org/foo/bar/blah/
我有以下代码(下面),这是低效的,因为它打印出来:
/path/to/stuff/org/foo/bar/
/path/to/stuff/org/foo/bar/
/path/to/stuff/org/foo/bar/blah/
/path/to/stuff/org/foo/bar/blah/
这是Java代码:
public class LocatorTest
{
@Test
public void testLocateDirectories()
throws IOException
{
long startTime = System.currentTimeMillis();
Files.walk(Paths.get("/path/to/stuff/"))
.filter(Files::isDirectory)
.forEach(Foo::printIfArtifactVersionDirectory);
long endTime = System.currentTimeMillis();
System.out.println("Executed in " + (endTime - startTime) + " ms.");
}
static class Foo
{
static void printIfArtifactVersionDirectory(Path path)
{
File f = path.toAbsolutePath().toFile();
List<String> filePaths = Arrays.asList(f.list(new MyExtFilenameFilter()));
if (!filePaths.isEmpty())
{
System.out.println(path.getParent());
}
}
}
}
过滤器:
public class MyExtFilenameFilter
implements FilenameFilter
{
@Override
public boolean accept(File dir, String name)
{
return name.endsWith(".ext");
}
}
答案 0 :(得分:34)
Files.walk(Paths.get("/path/to/stuff/"))
.filter(p -> p.toString().endsWith(".ext"))
.map(p -> p.getParent().getParent())
.distinct()
.forEach(System.out::println);
这将过滤所有具有扩展名的文件并获取其目录的父路径。 distinct
确保每个路径仅使用一次。
答案 1 :(得分:4)
您正在为所有访问过的目录调用方法printIfArtifactVersionDirectory
。我做了一点改变,显而易见:
static void printIfArtifactVersionDirectory(Path path) {
System.out.println("--- " + path);
...
}
有了这个额外的输出,你将得到:
--- C:\ Projects \ stuff
--- C:\ Projects \ stuff \ org
--- C:\ Projects \ stuff \ org \ foo
--- C:\ Projects \ stuff \ org \ foo \ bar
--- C:\ Projects \ stuff \ org \ foo \ bar \ 1.2.3
C:\项目\东西\组织\富\酒吧
--- C:\ Projects \ stuff \ org \ foo \ bar \ 1.2.4
C:\项目\东西\组织\富\酒吧
--- C:\ Projects \ stuff \ org \ foo \ bar \ blah
--- C:\ Projects \ stuff \ org \ foo \ bar \ blah \ 2.1
C:\项目\东西\组织\富\酒吧\等等
--- C:\ Projects \ stuff \ org \ foo \ bar \ blah \ 2.2
C:\ Projects \ stuff \ org \ foo \ bar \ blah
因此,您可以像拥有工件版本目录一样获得输出。如果您想记住您已经为一个目录输出了输出,那么您必须在某处存储此信息。一个快速实施可能是:
static class Foo {
private static final Set<Path> visited = new HashSet<>();
static void printIfArtifactVersionDirectory(Path path) {
...
Path parent = path.getParent();
if (!filePaths.isEmpty() && !visited.contains(parent)) {
visited.add(parent);
System.out.println(parent);
}
}
}
通过这个,您可以获得预期的输出:
C:\项目\东西\有机\ FOO \酒吧
C:\ Projects \ stuff \ org \ foo \ bar \ blah
更好的解决方案是使用该集来存储访问过的父母,并且只有在访问所有父母后才能打印:
static class PathStore {
private final Set<Path> store = new HashSet<>();
void visit(Path path) {
File f = path.toAbsolutePath().toFile();
List<String> filePaths = Arrays.asList(f.list(new MyExtFilenameFilter()));
if (!filePaths.isEmpty()) {
store.add(path.getParent());
}
}
void print() {
store.forEach(System.out::println);
}
}
用法:
PathStore pathStore = new PathStore();
Files.walk(Paths.get("/path/to/stuff/"))
.filter(Files::isDirectory)
.forEach(pathStore::visit);
pathStore.print();
答案 2 :(得分:1)
添加到@a-better-oliver's answer中,这是如果您的操作声明IOExceptions可以执行的操作。
您可以将过滤后的流视为<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li>
<input type="checkbox" class="check-negozio" data-npv="0">
<ul>
<li class="nav-item">
<input type="checkbox" class="check-cassa" data-cs="1">
</li>
<li>
<input type="checkbox" class="check-cassa" data-cs="5">
<ul>
<li>
<input type="checkbox" class="check-operatore" data-op="0">
</li>
</ul>
</li>
</ul>
</li>
</ul>
,然后在常规的for-each循环中执行操作。这样,您不必在lambda内部处理异常。
Iterable