0

Как правильно рекурсивно устанавливать права доступа к файлам в Python?

949

Каков "питоновский способ" рекурсивно установить владельца и группу для файлов в директории? Я мог бы просто передать команду 'chown -R' в оболочку, но мне кажется, что я упускаю что-то очевидное.

Я экспериментирую с этим кодом:

import os  
path = "/tmp/foo"  
for root, dirs, files in os.walk(path):  
  for momo in dirs:  
    os.chown(momo, 502, 20)

Этот код работает для установки владельца и группы для директорий, но не срабатывает для файлов. Я подозреваю, что файлы не получают полный путь, из-за чего chown не может их найти. Ошибка, которую я получаю:

OSError: [Errno 2] No such file or directory: 'foo.html'

Что я здесь упускаю?

5 ответ(ов)

0

Проблема, которую вы описываете, связана с тем, что списки dirs и files, возвращаемые функцией os.walk(), содержат только имена файлов и папок без полного пути. То есть они являются результатом функции basename(), и в них нет начального слеша / (в Windows это \). Для того чтобы ваш код корректно работал на любых уровнях вложенности, вам необходимо объединить имена директорий и файлов с root для получения полного пути.

Вот как это можно сделать:

import os  
path = "/tmp/foo"

# Изменение прав доступа для верхней директории
os.chmod(path, 502, 20)

for root, dirs, files in os.walk(path):
    # Установка прав на подкаталоги  
    for momo in dirs:
        os.chown(os.path.join(root, momo), 502, 20)

    # Установка прав на файлы
    for momo in files:
        os.chown(os.path.join(root, momo), 502, 20)

К удивлению, в модуле shutil не предусмотрена функция для выполнения этой задачи.

0

Как правильно отмечено выше, принятый ответ не учитывает файлы и каталоги на верхнем уровне. В других ответах используется os.walk, после чего происходит перебор dirnames и filenames. Однако, поскольку os.walk уже проходит по dirnames, вы можете пропустить цикл по dirnames и просто изменить владельца для текущего каталога (dirpath):

def recursive_chown(path, owner):
    for dirpath, dirnames, filenames in os.walk(path):
        shutil.chown(dirpath, owner)
        for filename in filenames:
            shutil.chown(os.path.join(dirpath, filename), owner)

Таким образом, этот подход позволяет оптимизировать процесс и исключить лишние итерации.

0

Вы можете просто передать команду 'chown -R' оболочке. Это самый простой способ, и он не совсем очевиден в вопросе, поэтому ради ясности, вы можете сделать это в одну строку, если вам не важна Windows:

os.system('chown -R 502 /tmp/foo')
0

Ваш код использует os.walk для обхода директории и изменения прав собственности на подкаталоги и файлы. Однако в вашем коде переменные aaa и bb для изменения владельца файла не были определены. Вы можете заменить их на подходящие значения для UID и GID.

Вот исправленный код с заменой aaa на 1001 (предполагаемый UID) и bb на 1002 (предполагаемый GID):

import os

path = "/tmp/foo"
for root, dirs, files in os.walk(path):
    for momo in dirs:
        os.chown(os.path.join(root, momo), 502, 20)  # Изменение владельца на каталогах
    for file in files:
        fname = os.path.join(root, file)
        os.chown(fname, 1001, 1002)  # Изменение владельца на файлах

Пожалуйста, убедитесь, что UID и GID, которые вы указываете, существуют на вашей системе, и что у вас есть необходимые права для выполнения этой операции. Вы можете использовать os.getuid() и os.getgid(), чтобы получить значения текущего пользователя и группы, если это необходимо.

0

Попробуйте использовать os.path.join(root, momo), это вернет вам полный путь.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь