Как правильно рекурсивно устанавливать права доступа к файлам в Python?
Каков "питоновский способ" рекурсивно установить владельца и группу для файлов в директории? Я мог бы просто передать команду '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 ответ(ов)
Проблема, которую вы описываете, связана с тем, что списки 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 не предусмотрена функция для выполнения этой задачи.
Как правильно отмечено выше, принятый ответ не учитывает файлы и каталоги на верхнем уровне. В других ответах используется 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)
Таким образом, этот подход позволяет оптимизировать процесс и исключить лишние итерации.
Вы можете просто передать команду 'chown -R' оболочке. Это самый простой способ, и он не совсем очевиден в вопросе, поэтому ради ясности, вы можете сделать это в одну строку, если вам не важна Windows:
os.system('chown -R 502 /tmp/foo')
Ваш код использует 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(), чтобы получить значения текущего пользователя и группы, если это необходимо.
Попробуйте использовать os.path.join(root, momo), это вернет вам полный путь.
Максимальная глубина рекурсии: как ее увеличить?
Как изменить порядок столбцов в DataFrame?
'pip' не распознан как командa внутреннего или внешнего формата
Почему statistics.mean() работает так медленно?
Есть ли разница между поднятием экземпляра класса Exception и самого класса Exception?