我想确保目录树中的正确权限(目录为0755,文件为644)。这是我的班级:
package NRF_Utils;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import static java.nio.file.FileVisitResult.*;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Set;
import java.util.logging.Logger;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
public class DirectoryTreeOperations {
private static final Logger log = Logger.getLogger("spv." + DirectoryTreeOperations.class.getName());
public static boolean setPermissions(String root, String directoryPermissions, String filePermissions) {
boolean result = true;
//declaring the path to delete
final Path path = Paths.get(root);
final Set<PosixFilePermission> dirPermissions = PosixFilePermissions.fromString(directoryPermissions);
final Set<PosixFilePermission> filPermissions = PosixFilePermissions.fromString(filePermissions);
try {
Files.walkFileTree(path, new FileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir,
BasicFileAttributes attrs) throws IOException {
System.out.println("setting dir permission on " + dir);
Files.setPosixFilePermissions(dir, dirPermissions);
return CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file,
BasicFileAttributes attrs) throws IOException {
System.out.println("setting file permission on " + file);
Files.setPosixFilePermissions(file, filPermissions);
return CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc)
throws IOException {
log.severe("visitFileFailed failed on " + file + " : " + exc);
return CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir,
IOException exc) throws IOException {
return CONTINUE;
}
});
} catch (IOException e) {
log.severe("setPermissions failed " + e);
result = false;
}
return result;
}
// TODO remove and provide a proper unit test
public static void main(String [] arg) {
System.out.println ("setPermissions returned: " + setPermissions("/tmp/x", "rwxr-xr-x", "rw-r--r--"));
}
}
为了进行测试,我做了:
mkdir -p /tmp/x/y/z;touch /tmp/x/y/z/f;chmod 000 /tmp/x/y/z
输出结果为:
setting dir permission on /tmp/x
setting dir permission on /tmp/x/y
setPermissions returned: true
nov. 26, 2017 2:45:00 PM NRF_Utils.DirectoryTreeOperations$1 visitFileFailed
GRAVE: visitFileFailed failed on /tmp/x/y/z : java.nio.file.AccessDeniedException: /tmp/x/y/z
似乎java不想浏览目录树,因为权限错误,但我的目的是探索目录树来修复权限。 API是疯了吗?
答案 0 :(得分:5)
它看起来似乎很奇怪,所以也许不是一个疯狂的API,但实现当然不能满足使用preVisitDirectory()来使目录可访问的特定情况。
Files.walkFileTree()
doc说:
如果文件是目录,并且无法打开目录, 然后使用I / O异常调用visitFileFailed方法, 之后,默认情况下,文件树步行继续在下一个步骤 兄弟姐妹的目录。
并查看实现,它确实尝试在调用visitor.preVisitDirectory()
之前打开目录,这解释了您遇到的问题。
作为一个解决方案,您可以获取FileTreeWalker.java源代码,并在您自己的本地版本的FileTreeWalker中进行微调 - 直接查找对visitor.preVisitDirectory()
的调用并移动打开的目录代码在那之后发生。然后将您的代码更改为:
new FileTreeWalker(EnumSet.noneOf(FileVisitOption.class), new FileVisitor<Path>() {
...
}, Integer.MAX_VALUE).walk(path);
当你跑步时,你会得到:
setting dir permission on /tmp/x
setting dir permission on /tmp/x/y
setting dir permission on /tmp/x/y/z
setting file permission on /tmp/x/y/z/f
setPermissions returned: true
显示了FileVisitor
的实施情况。
希望有所帮助。
答案 1 :(得分:3)
当您从命令行执行chmod 755 /tmp/x/y/z
时,它不会检查z
本身的权限。只要您有足够的y
访问权限,就可以在chmod
上执行z
。
OTOH,如果您查看Files.walkFileTree
的{{3}},它实际上会尝试使用自己的visit
方法访问每个目标文件,收集文件属性等,之前它会调用您的访问者方法。因此拒绝访问错误。
从表面上看,您可能需要滚动自己的文件树助行器,在那里您可以继续更改权限,而无需先尝试访问目标路径。
答案 2 :(得分:1)
DEFINE('DB_USER', 'root'); // default user name
DEFINE('DB_PASSWORD', ''); // empty password just open single quote and close
的唯一问题是它不会在没有搜索权限的目录上调用walkFileTree
。您可以通过在walkFileTree查找的位置之前修复权限来解决此问题。
即,通过手动扫描递送到preVisitDirectory()
的任何目录的直接子项并在那里应用权限(而不是preVisitDirectoy()
):
visitFile
然后你可以评论 @Override
public FileVisitResult preVisitDirectory(Path dir,
BasicFileAttributes attrs) throws IOException {
for(File f : new File(dir.toUri()).listFiles()) { //iterate over the contents of the directory
System.out.println("setting dir permission on " + f);
Files.setPosixFilePermissions(dir.resolve(f.getName()), dirPermissions);
}
//System.out.println("setting dir permission on " + dir);
//Files.setPosixFilePermissions(dir, dirPermissions);
return CONTINUE;
}
的身体:
visitFile()
由于我们现在将权限应用于walk所在的下一层,我们需要在try块内部进行额外的调用:
@Override
public FileVisitResult visitFile(Path file,
BasicFileAttributes attrs) throws IOException {
// System.out.println("setting file permission on " + file);
// Files.setPosixFilePermissions(file, filPermissions);
return CONTINUE;
}
以下是整个事情(好吧,为方便起见,我取消了包裹声明):
System.out.println("setting dir permission on " + path); //in case the initial path needs fixing
Files.setPosixFilePermissions(path, dirPermissions);
在示例案例上运行时:
import java.io.File;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import static java.nio.file.FileVisitResult.*;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Set;
import java.util.logging.Logger;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
public class DirectoryTreeOperations {
private static final Logger log = Logger.getLogger("spv." + DirectoryTreeOperations.class.getName());
public static boolean setPermissions(String root, String directoryPermissions, String filePermissions) {
boolean result = true;
//declaring the path to delete
final Path path = Paths.get(root);
final Set<PosixFilePermission> dirPermissions = PosixFilePermissions.fromString(directoryPermissions);
final Set<PosixFilePermission> filPermissions = PosixFilePermissions.fromString(filePermissions);
try {
System.out.println("setting dir permission on " + path); //in case the initial path needs fixing
Files.setPosixFilePermissions(path, dirPermissions);
Files.walkFileTree(path, new FileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir,
BasicFileAttributes attrs) throws IOException {
for(File f : new File(dir.toUri()).listFiles()) { //iterate over the contents of the directory
System.out.println("setting dir permission on " + f);
Files.setPosixFilePermissions(dir.resolve(f.getName()), dirPermissions);
}
//System.out.println("setting dir permission on " + dir);
//Files.setPosixFilePermissions(dir, dirPermissions);
return CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file,
BasicFileAttributes attrs) throws IOException {
// System.out.println("setting file permission on " + file);
// Files.setPosixFilePermissions(file, filPermissions);
return CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc)
throws IOException {
log.severe("visitFileFailed failed on " + file + " : " + exc);
return CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir,
IOException exc) throws IOException {
return CONTINUE;
}
});
} catch (IOException e) {
log.severe("setPermissions failed " + e);
result = false;
}
return result;
}
// TODO remove and provide a proper unit test
public static void main(String [] arg) {
System.out.println ("setPermissions returned: " + setPermissions("/tmp/x", "rwxr-xr-x", "rw-r--r--"));
}
}