用Java递归设置文件的用户,组和权限

Posted by Night Field's Blog on February 16, 2020

前言

自从1.7版本开始,Java引入了Nio包,提供了更强大的IO功能。 本文简单介绍如何用java.nio.file.attribute下的工具类修改文件的权限,用户和组。因为本类库是针对Posix类系统的的,所以主要适用于LinuxMac上(实测Win7不支持)。

测试样例

测试代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
public class FileTest {
    public static void main(String[] args) throws Exception {
        // 检查操作系统是否支持posix。
        // 一般像mac和linux都支持,经测试win7不支持
        boolean supportPosix = FileSystems.getDefault().supportedFileAttributeViews().contains("posix");
        if (!supportPosix) {
            System.out.println("Your OS does not support posix.");
            return;
        }

        // 将要设置的权限:用户,组,以及三组读/写/执行的权限
        String owner = "testowner";
        String group = "testgroup";
        PosixFilePermission[] permissions = {
                PosixFilePermission.OWNER_READ,
                PosixFilePermission.OWNER_WRITE,
                PosixFilePermission.OWNER_EXECUTE,
                PosixFilePermission.GROUP_READ,
                PosixFilePermission.GROUP_WRITE,
                PosixFilePermission.GROUP_EXECUTE,
                PosixFilePermission.OTHERS_READ,
                PosixFilePermission.OTHERS_WRITE,
                PosixFilePermission.OTHERS_EXECUTE,
        };
        changePermission("/opt/test", true, owner, group, permissions);
    }

    private static void changePermission(String pathStr, boolean isRecurisive, String owner, String group, PosixFilePermission... permissions) {
        Path path = Paths.get(pathStr);
        if (!Files.exists(path)) {
            System.out.println(pathStr + " not exists!");
            return;
        };
        try {
            System.out.format("Before, %s ", pathStr);
            readTargetPermission(path);

            // 设置permission,相当于linux命令chmod
            Set<PosixFilePermission> perms = new HashSet<>();
            for (PosixFilePermission permission : permissions) {
                perms.add(permission);
            }
            Files.setPosixFilePermissions(path, perms);

            // 设置用户和组,相当于linux命令chown
            // 要保证用户和组存在,否则lookupService会抛UserPrincipalNotFoundException
            UserPrincipalLookupService lookupService = FileSystems.getDefault().getUserPrincipalLookupService();
            GroupPrincipal groupPrincipal = lookupService.lookupPrincipalByGroupName(group);
            UserPrincipal userPrincipal = lookupService.lookupPrincipalByName(owner);
            PosixFileAttributeView view = Files.getFileAttributeView(path, PosixFileAttributeView.class);
            view.setGroup(groupPrincipal);
            view.setOwner(userPrincipal);

            System.out.format("After, %s ", pathStr);
            readTargetPermission(path);
        } catch (IOException e) {
            if (e instanceof UserPrincipalNotFoundException) {
                System.out.format("group '%s' or owner '%s' not exist%n", group, owner);
                return;
            }
            System.out.format("%s set permission failed%n", pathStr);
            e.printStackTrace();
        }

        // 当是目录的时候,递归设置文件权限
        if (isRecurisive && Files.isDirectory(path)) {
            try (DirectoryStream<Path> ds = Files.newDirectoryStream(path)) {
                for (Path subPath : ds) {
                    changePermission(pathStr + File.separator + subPath.getFileName(), true, owner, group, permissions);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    // print current permission of folder/file
    private static void readTargetPermission(Path path) throws IOException {
        Set<PosixFilePermission> filePermissions = Files.readAttributes(path, PosixFileAttributes.class).permissions();
        GroupPrincipal fileGroup = Files.readAttributes(path, PosixFileAttributes.class).group();
        UserPrincipal fileOwner = Files.readAttributes(path, PosixFileAttributes.class).owner();
        System.out.format("permissions: %s, user: %s, group: %s%n", PosixFilePermissions.toString(filePermissions), fileOwner, fileGroup); 
    }
}

控制台输出如下:

1
2
3
4
5
6
7
8
Before, /opt/test permissions: rwx------, user: root, group: root
After, /opt/test permissions: rwxrwxrwx, user: testowner, group: testgroup
Before, /opt/test/testFolder permissions: rwx------, user: root, group: root
After, /opt/test/testFolder permissions: rwxrwxrwx, user: testowner, group: testgroup
Before, /opt/test/testFolder/testFile2 permissions: rw-------, user: root, group: root
After, /opt/test/testFolder/testFile2 permissions: rwxrwxrwx, user: testowner, group: testgroup
Before, /opt/test/testFile permissions: rw-------, user: root, group: root
After, /opt/test/testFile permissions: rwxrwxrwx, user: testowner, group: testgroup

通过对比,目录以及该目录下的所有子目录和文件,权限都变成了777,用户都由root变为了testowner,组都有root变为了testgroup

总结

Java Nio提供了强大及友好的类库,方便我们对文件进行各种操作。