Как правильно рекурсивно устанавливать права доступа к файлам в 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?