web-dev-qa-db-fra.com

Quelle est la méthode Python pour définir récursivement les autorisations de fichier?

Quelle est la "méthode python" pour définir récursivement le propriétaire et le groupe sur des fichiers dans un répertoire? Je pourrais simplement passer une commande 'chown -R' à Shell, mais j'ai l'impression de manquer quelque chose d'évident.

Je boude avec ça:


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

Cela semble fonctionner pour définir le répertoire, mais échoue lorsqu'il est appliqué aux fichiers. Je soupçonne que les fichiers n'obtiennent pas le chemin complet, donc chown échoue car il ne peut pas trouver les fichiers. L'erreur est:

'OSError: [Errno 2] Aucun fichier ou répertoire de ce type:' foo.html '

Qu'est-ce que je néglige ici?

35
Geoff

Les listes dirs et files sont toutes toujours relatives à root - c'est-à-dire qu'elles sont la basename() des fichiers/dossiers, c'est-à-dire qu'elles ne le font pas avoir un / en eux (ou \ sur windows). Vous devez joindre les répertoires/fichiers à root pour obtenir leur chemin complet si vous voulez que votre code fonctionne à des niveaux infinis de récursivité:

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 momo in files:
    os.chown(os.path.join(root, momo), 502, 20)

Je suis surpris que le module shutil n'ait pas de fonction pour cela.

43
too much php
import os  
path = "/tmp/foo"  
for root, dirs, files in os.walk(path):  
  for momo in dirs:  
    os.chown(momo, 502, 20)
  for file in files:
     fname = os.path.join(root, file)
     os.chown(fname, aaa, bb)

remplacez aaa et bb comme bon vous semble

6
Escualo

essayez os.path.join(root,momo) qui vous donnera le chemin complet

4
Kugel

La réponse acceptée manque les fichiers de niveau supérieur. Il s'agit de l'équivalent réel de chown -R.

import os

path = "/tmp/foo"

os.chown(path, 502, 20)
for dirpath, dirnames, filenames in os.walk(path):
    for dname in dirnames:
        os.chown(os.path.join(dirpath, dname), 502, 20)
    for fname in filenames:
        os.chown(os.path.join(dirpath, fname), 502, 20)
2
nlsun

Comme indiqué correctement ci-dessus, la réponse acceptée ne contient ni fichiers ni répertoires de niveau supérieur. Les autres réponses utilisent os.walk puis parcourez dirnames et filenames. Cependant, os.walk passe par dirnames de toute façon, vous pouvez donc ignorer la boucle par dirnames et simplement chown le répertoire courant (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)
2
Christian Alis

Voici une fonction que j'ai écrite qui utilise glob pour répertorier récursivement les fichiers et modifier leurs autorisations.

import os
import glob
def recursive_file_permissions(path,mode,uid=-1,gid=-1):
        '''
        Recursively updates file permissions on a given path.
        UID and GID default to -1, and mode is required
        '''
    for item in glob.glob(path+'/*'):
        if os.path.isdir(item):
            recursive_file_permissions(os.path.join(path,item),mode,uid,gid)
        else:
            try:
                os.chown(os.path.join(path,item),uid,gid)
                os.chmod(os.path.join(path,item),mode)
            except:
                print('File permissions on {0} not updated due to error.'.format(os.path.join(path,item)))

ce n'est pas parfait, mais m'a amené là où je devais être

2
Keith Hamilton

N'oubliez pas non plus la boucle for f in files. De même, n'oubliez pas de os.path.join(root, f) pour obtenir le chemin complet.

1
dash-tom-bang

Je pourrais simplement passer une commande 'chown -R' à Shell

C'est le moyen le plus simple et se perd un peu dans la question, donc juste pour plus de clarté, vous pouvez le faire en une seule ligne si vous ne vous souciez pas de Windows:

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