What is the Python way for recursively setting file permissions?

58,569

Solution 1

The dirs and files lists are all always relative to root - i.e., they are the basename() of the files/folders, i.e. they don't have a / in them (or \ on windows). You need to join the dirs/files to root to get their whole path if you want your code to work to infinite levels of recursion:

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)

I'm suprised the shutil module doesn't have a function for this.

Solution 2

As correctly pointed out above, the accepted answer misses top-level files and directories. The other answers use os.walk then loop through dirnames and filenames. However, os.walk goes through dirnames anyway, so you can skip looping through dirnames and just chown the current directory (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)

Solution 3

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)

substitute aaa and bb as you please

Solution 4

I could just pass a 'chown -R' command to shell

This is the simplest way, and gets lost in the question a bit, so just for clarity, you can do this in one line if you don't care about Windows:

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

Solution 5

try os.path.join(root,momo) that will give you full path

Share:
58,569

Related videos on Youtube

Geoff
Author by

Geoff

Updated on January 16, 2021

Comments

  • Geoff
    Geoff over 3 years

    What's the "python way" to recursively set the owner and group to files in a directory? I could just pass a 'chown -R' command to shell, but I feel like I'm missing something obvious.

    I'm mucking about with this:

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

    This seems to work for setting the directory, but fails when applied to files. I suspect the files are not getting the whole path, so chown fails since it can't find the files. The error is:

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

    What am I overlooking here?

  • Avindra Goolcharan
    Avindra Goolcharan over 8 years
    This has a bug which I just saw in my co-worker's code in production :-) The top level directory specified is not being chowned. I suggested an edit with a fix, hopefully it gets approved.
  • Avindra Goolcharan
    Avindra Goolcharan over 8 years
    As in the accepted comment, /tmp/foo will NOT have the owner properly set. See my comments above.
  • Avindra Goolcharan
    Avindra Goolcharan over 8 years
    So my edit was rejected - good look to anyone who uses this and encounters the bug where /tmp/foo does NOT have its permissions changed. Good job moderating SO pythonians 👍👍👍
  • fatal_error
    fatal_error about 8 years
    @AvindraGoolcharan good catch - hopefully that was what you had in mind!
  • Christian Alis
    Christian Alis almost 5 years
    No need to loop through dirnames since os.walk will go through all directories anyway. See my answer.
  • Christian Alis
    Christian Alis almost 5 years
    No need to loop through dirs since os.walk will go through all directories anyway. See my answer.
  • gerardw
    gerardw over 3 years
    Why shutil.chown instead of os.chown?
  • wedgef5
    wedgef5 over 3 years
    @gerardw I believe os.chown() only takes numeric uid and gid, whereas shutil.chown() will accept names or numeric IDs.
  • jrh
    jrh over 2 years
    @AvindraGoolcharan Edits 1, 2, strike 3 you're out. Apparently 9 reviewers think adding os.chown(path, 502, 20) "deviates from intent", "should be a comment", or "is worth making a whole new answer for". Really...? One line? Do all these people not know that chmod -R some_dir would change some_dir and all its child directories? I know you all are terrified about approving code edits, but still, this is silly