I need to check whether a given path is a subpath anywhere within another path and was wondering whether there exists such a method already before writing my own.
Here is some code that may help to understand the problem:
Path someRealPath = Paths.get("/tmp/some/path/to/somewhere");
Path subpathToCheck = Paths.get("some/path");
// I am expecting something similar as follows:
someRealPath.contains(subPathToCheck) // should return true in this case
someRealPath.contains(Paths.get("some/to")) // should return false
I already saw relativize
, but I don't think that's the easiest way to solve the problem. The simplest I came up with was normalize().toString().contains(/* other normalized string path */)
. But maybe there is an easier way? Lots of methods inside Paths
look as if this functionality must already be in there. Maybe I am just not seeing it.
What I came up with is the following:
boolean containsSubPath(Path someRealPath, Path subPathToCheck) {
return someRealPath.normalize()
.toString()
.contains(subPathToCheck.normalize()
.toString());
}
This way I am able to just call:
containsSubPath(Paths.get("/tmp/some/path/to/somewhere"), Paths.get("some/path"));
As Thomas Kläger pointed out, this solution matches also paths, that are only substrings of a real path (which for my use case would also be ok).
Here is another solution that is probably more correct (for complete matching subpaths), but still not as short as I would like it to be (now corrected due to Kabhals input):
static boolean containsSubPath(Path realPath, Path subPath) {
for (Path realPathSegment : realPath.normalize()) {
if (containsSubPath(realPathSegment.iterator(), subPath.normalize().iterator())) {
return true;
}
}
return false;
}
private static boolean containsSubPath(Iterator<Path> realPathIterator, Iterator<Path> subPathIterator) {
var hasEntries = realPathIterator.hasNext() && subPathIterator.hasNext();
while (realPathIterator.hasNext() && subPathIterator.hasNext()) {
Path realPathSegment = realPathIterator.next();
Path subPathSegment = subPathIterator.next();
if (!Objects.equals(realPathSegment, subPathSegment))
return false;
}
return hasEntries;
}
Example calls with expected output:
containsSubPath(Paths.get("/tmp/some/path/to/somewhere"), Paths.get("some/path")) // true
containsSubPath(Paths.get("/tmp/some/path/to/somewhere"), Paths.get("me/pa")) // false
If you need to use it as BinaryOperator
just use the method reference instead, i.e. YourClass::containsSubPath
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With