I would like to check whether an existing file is in a specific directory or a subdirectory of that.
I have two File objects.
File dir;
File file;
<
If you plan to works with file and filenames heavly check apache fileutils and filenameutils libraries. Are full of useful (and portale if portability is mamdatory) functions
You can do this, however it won't catch every use case e.g. dir = /somedir/../tmp/dir/etc..., unless that's how the file was defined also.
import java.nio.file.Path;
import java.nio.file.Paths;
public class FileTest {
public static void main(final String... args) {
final Path dir = Paths.get("/tmp/dir").toAbsolutePath();
final Path file = Paths.get("/tmp/dir/subdir1/subdir2/file.txt").toAbsolutePath();
System.out.println("Dir: " + dir);
System.out.println("File: " + file);
final boolean valid = file.startsWith(dir);
System.out.println("Valid: " + valid);
}
}
In order for the checks to work correctly, you really need to map these using toRealPath()
or, in your example, getCanonicalPath()
, but you then have to handle exceptions for these examples which is absolutely correct that you should do so.
In addition to the asnwer from rocketboy, use getCanonicalPath()
instad of getAbsolutePath()
so \dir\dir2\..\file
is converted to \dir\file
:
boolean areRelated = file.getCanonicalPath().contains(dir.getCanonicalPath() + File.separator);
System.out.println(areRelated);
or
boolean areRelated = child.getCanonicalPath().startsWith(parent.getCanonicalPath() + File.separator);
Do not forget to catch any Exception
with try {...} catch {...}
.
NOTE: You can use FileSystem.getSeparator()
instead of File.separator
. The 'correct' way of doing this will be to get the getCanonicalPath()
of the directory that you are going to check against as a String
, then check if ends with a File.separator
and if not then add File.separator
to the end of that String
, to avoid double slashes. This way you skip future odd behaviours if Java decides to return directories with a slash in the end or if your directory string comes from somewhere else than Java.io.File
.
NOTE2: Thanx to @david for pointing the File.separator
problem.
You can traverse File Tree starting from your specific DIR.
At Java 7, there is Files.walkFileTree
method. You have only to write your own visitor
to check if current node is searched file. More doc:
http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#walkFileTree%28java.nio.file.Path,%20java.util.Set,%20int,%20java.nio.file.FileVisitor%29
I would create a small utility method:
public static boolean isInSubDirectory(File dir, File file) {
if (file == null)
return false;
if (file.equals(dir))
return true;
return isInSubDirectory(dir, file.getParentFile());
}
This method looks pretty solid:
/**
* Checks, whether the child directory is a subdirectory of the base
* directory.
*
* @param base the base directory.
* @param child the suspected child directory.
* @return true, if the child is a subdirectory of the base directory.
* @throws IOException if an IOError occured during the test.
*/
public boolean isSubDirectory(File base, File child)
throws IOException {
base = base.getCanonicalFile();
child = child.getCanonicalFile();
File parentFile = child;
while (parentFile != null) {
if (base.equals(parentFile)) {
return true;
}
parentFile = parentFile.getParentFile();
}
return false;
}
Source
It is similar to the solution by dacwe but doesn't use recursion (though that shouldn't make a big difference in this case).