Як я можу програматично змінити дозволи файлів?


115

У Java я динамічно створюю набір файлів, і я хотів би змінити дозволи на файли для цих файлів у файловій системі linux / unix. Я хотів би мати можливість виконувати Java-еквівалент chmod. Чи можлива така Java 5? Якщо так, то як?

Я знаю, що в Java 6 Fileоб'єкт має setReadable()/ setWritable()методи. Я також знаю, що можу зробити системний дзвінок, щоб це зробити, але я хотів би уникнути цього, якщо можливо.


2
Примітка для інших: Для існуючих файлів, так як Java 7, ви можете використовувати цей однострочнікі:Files.setPosixFilePermissions(path, PosixFilePermissions.fromString("rwxr-x---"))
Том

Відповіді:


110

Повний контроль над атрибутами файлів доступний в Java 7, як частина "нового" нового засобу вводу- виводу ( NIO.2 ). Наприклад, дозволи на POSIX можуть бути встановлені для існуючого файлу за допомогою setPosixFilePermissions(), або атомним чином при створенні файлу методами, такими як createFile()або newByteChannel().

Ви можете створити набір дозволів за допомогою EnumSet.of(), але хелперний метод PosixFilePermissions.fromString()використовуватиме звичайний формат, який буде більш читабельним для багатьох розробників. Для API, які приймають FileAttribute, ви можете обернути набір дозволів за допомогою PosixFilePermissions.asFileAttribute().

Set<PosixFilePermission> ownerWritable = PosixFilePermissions.fromString("rw-r--r--");
FileAttribute<?> permissions = PosixFilePermissions.asFileAttribute(ownerWritable);
Files.createFile(path, permissions);

У попередніх версіях Java execпоширеним підходом є використання власного коду або утиліти командного рядка -ing.


4
вибравши цю, оскільки я не маю можливості використовувати відповідь Марті Ламб.
Рой Ріко

1
Я серйозно не можу повірити, що минуло більше шести років з того часу, як вони почали працювати над NIO.2, і це все ще не в транспортному JRE.
clee

8
Приклад коду може бути корисним у вашій відповіді.
Рікардо Гладуелл

2
Ця відповідь stackoverflow.com/a/32331442/290182 по @PixelsTech перевершує , так як він забезпечує приклад коду
beldaz

1
@SteveB Все встановлено.
erickson

43

Окрім пропозицій erickson, є також jna , що дозволяє телефонувати в рідні бібліотеки без використання jni. Це приголомшливо просте у використанні, і я його використав у кількох проектах з великим успіхом.

Єдине застереження полягає в тому, що він повільніше, ніж jni, тому якщо ви робите це для дуже великої кількості файлів, які можуть бути проблемою для вас.

(Редагування для додавання прикладу)

Ось повний приклад jna chmod:

import com.sun.jna.Library;
import com.sun.jna.Native;

public class Main {
    private static CLibrary libc = (CLibrary) Native.loadLibrary("c", CLibrary.class);

    public static void main(String[] args) {
        libc.chmod("/path/to/file", 0755);
    }
}

interface CLibrary extends Library {
    public int chmod(String path, int mode);
}

1
JNA - такий приємний інструмент для рідних дзвінків!
еріксон

3
Для правильної обробки помилок, CLibrary.chmod () необхідно оголосити, щоб кинути com.sun.jna.LastErrorException. Це єдиний безпечний для потоків спосіб отримання значення errno, встановленого викликом chmod (). В іншому випадку ви можете отримати статус успіху / невдачі з поверненого значення, але не від фактичного коду помилки.
Саймон Кіссане

30

До Java 6 не підтримується оновлення дозволу на файлі на рівні Java. Вам належить реалізувати власний власний метод або зателефонувати, Runtime.exec()щоб виконати команду рівня ОС, наприклад chmod .

Починаючи з Java 6, ви можете використовувати File.setReadable()/File.setWritable()/File.setExecutable()для встановлення дозволів файлів. Але вона не імітує файлову систему POSIX, яка дозволяє встановлювати дозвіл для різних користувачів. File.setXXX () дозволяє встановлювати дозвіл власнику та всім іншим.

Починаючи з Java 7, вводиться дозвіл файлів POSIX. Ви можете встановити дозволи файлів, як те, що ви робили в * nix системах. Синтаксис:

File file = new File("file4.txt");
file.createNewFile();

Set<PosixFilePermission> perms = new HashSet<>();
perms.add(PosixFilePermission.OWNER_READ);
perms.add(PosixFilePermission.OWNER_WRITE);

Files.setPosixFilePermissions(file.toPath(), perms);

Цей метод можна використовувати лише у файловій системі POSIX, це означає, що ви не можете його викликати в системі Windows.

Щоб отримати детальну інформацію про управління дозволом на файли, рекомендую прочитати цю публікацію .


18

для Windows 7 з nio 2.0:

public static void main(String[] args) throws IOException
{
    Path file = Paths.get("c:/touch.txt");
    AclFileAttributeView aclAttr = Files.getFileAttributeView(file, AclFileAttributeView.class);
    System.out.println(aclAttr.getOwner());
    for(AclEntry aclEntry : aclAttr.getAcl()){
        System.out.println(aclEntry);
    }
    System.out.println();

    UserPrincipalLookupService upls = file.getFileSystem().getUserPrincipalLookupService();
    UserPrincipal user = upls.lookupPrincipalByName(System.getProperty("user.name"));
    AclEntry.Builder builder = AclEntry.newBuilder();       
    builder.setPermissions( EnumSet.of(AclEntryPermission.READ_DATA, AclEntryPermission.EXECUTE, 
            AclEntryPermission.READ_ACL, AclEntryPermission.READ_ATTRIBUTES, AclEntryPermission.READ_NAMED_ATTRS,
            AclEntryPermission.WRITE_ACL, AclEntryPermission.DELETE
    ));
    builder.setPrincipal(user);
    builder.setType(AclEntryType.ALLOW);
    aclAttr.setAcl(Collections.singletonList(builder.build()));
}

1
це чудово працює. Єдина модифікація була зроблена для методу lookupPrincipalByName (), я надіслав System.getProperty ("user.name") замість "user". Нарешті це виглядало як upls.lookupPrincipalByName (System.getProperty ("ім'я користувача")); Дякуємо за код!
isuru chathuranga

@bob .. чи можете ви мені дати клас AclFileAttributeView та UserPrincipalLookupService .. bcz це не може вирішити .. ви відповісте, здається, працює .. і я хочу реалізувати
Sagar Chavada

java.nio.file.attribute.AclFileAttributeView та java.nio.file.attribute.UserPrincipalLookupService, для компіляції та запуску потрібен jdk 1.7+.
боб

11

Якщо ви хочете встановити дозвіл 777 на створений файл, тоді ви можете скористатися наступним методом:

public void setPermission(File file) throws IOException{
    Set<PosixFilePermission> perms = new HashSet<>();
    perms.add(PosixFilePermission.OWNER_READ);
    perms.add(PosixFilePermission.OWNER_WRITE);
    perms.add(PosixFilePermission.OWNER_EXECUTE);

    perms.add(PosixFilePermission.OTHERS_READ);
    perms.add(PosixFilePermission.OTHERS_WRITE);
    perms.add(PosixFilePermission.OTHERS_EXECUTE);

    perms.add(PosixFilePermission.GROUP_READ);
    perms.add(PosixFilePermission.GROUP_WRITE);
    perms.add(PosixFilePermission.GROUP_EXECUTE);

    Files.setPosixFilePermissions(file.toPath(), perms);
}

10

Просто для оновлення цієї відповіді, якщо хтось не натрапить на це пізніше, оскільки JDK 6 ви можете використовувати

File file = new File('/directory/to/file');
file.setWritable(boolean);
file.setReadable(boolean);
file.setExecutable(boolean);

Ви можете знайти документацію у файлі Oracle (Java Platform SE 7) . Майте на увазі, що ці команди працюють лише у тому випадку, коли поточний користувач має право власності або записує доступ до цього файла. Мені відомо, що ОП хотів отримати тип chmod для більш складної конфігурації користувача. вони встановлять параметр для всіх користувачів.


Класно, ле савюр!
khawarizmi

Я ще протестував його з Openjdk 11.0.6 під Debian, він працює!
Хартмут Шорріг

4

Ви можете використовувати методи класу Файл: http://docs.oracle.com/javase/7/docs/api/java/io/File.html


3
Будь ласка, погляньте на це питання. Рой Ріко знає про setReadable () і setWritable (), але вони дозволяють лише змінювати дозволи власника, а не групування чи всі права чи будь-які інші прапори.
ChrisB

3

для Oralce Java 6:

private static int chmod(String filename, int mode) {
    try {
        Class<?> fspClass = Class.forName("java.util.prefs.FileSystemPreferences");
        Method chmodMethod = fspClass.getDeclaredMethod("chmod", String.class, Integer.TYPE);
        chmodMethod.setAccessible(true);
        return (Integer)chmodMethod.invoke(null, filename, mode);
    } catch (Throwable ex) {
        return -1;
    }
}

працює під solaris / linux.


слід пам’ятати, що FileSystemPreferencesобертається демонова Timerнитка, коли вона завантажена. він також додає гачок відключення, але для деяких застосувань це все ще може бути проблематично.
thrau

2

Apache ant chmod (не дуже елегантний, додаючи його для повноти) кредит поділився з @msorsky

    Chmod chmod = new Chmod();
    chmod.setProject(new Project());
    FileSet mySet = new FileSet();
    mySet.setDir(new File("/my/path"));
    mySet.setIncludes("**");
    chmod.addFileset(mySet);
    chmod.setPerm("+w");
    chmod.setType(new FileDirBoth());
    chmod.execute();



0
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.PosixFileAttributes;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
import java.util.Set;

public class FileAndDirectory1 {
    public static void main(String[] args) {
        
        File file = new File("fileTest1.txt");
        System.out.println(file.getAbsoluteFile());
        try {
            //file.createNewFile();
            if(!file.exists())
            {
                //PosixFilePermission is an enum class, PosixFilePermissions is a final class
                
                //create file permissions from string
                Set<PosixFilePermission> filePermissions = PosixFilePermissions.fromString("---------"/* "rwxrwxrwx" */);
                FileAttribute<?> permissions = PosixFilePermissions.asFileAttribute(filePermissions);
                Files.createFile(file.toPath(), permissions);
                // printing the permissions associated with the file
                System.out.println("Executable: " + file.canExecute());
                System.out.println("Readable: " + file.canRead());
                System.out.println("Writable: "+ file.canWrite());

                file.setExecutable(true);
                file.setReadable(true);
                file.setWritable(true);
            }
            else
            {
                //modify permissions
                
                //get the permission using file attributes
                Set<PosixFilePermission> perms = Files.readAttributes(file.toPath(), PosixFileAttributes.class).permissions();
                perms.remove(PosixFilePermission.OWNER_WRITE);

                perms.add(PosixFilePermission.OWNER_READ);
                perms.add(PosixFilePermission.OWNER_EXECUTE);
                perms.add(PosixFilePermission.GROUP_WRITE);
                perms.add(PosixFilePermission.GROUP_READ);
                perms.add(PosixFilePermission.GROUP_EXECUTE);
                perms.add(PosixFilePermission.OTHERS_WRITE);
                perms.add(PosixFilePermission.OTHERS_READ);
                perms.add(PosixFilePermission.OTHERS_EXECUTE);
                Files.setPosixFilePermissions(file.toPath(), perms);

                System.out.println("Executable: " + file.canExecute());
                System.out.println("Readable: " + file.canRead());
                System.out.println("Writable: "+ file.canWrite());

                file.delete();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        Path path = Paths.get(String.valueOf(file));
        System.out.println(path);
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.