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?
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.
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
try os.path.join(root,momo) that will give you full path
Here is a function i wrote that uses glob to recursively list files and change their permissions.
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)))
it's not perfect, but got me where I needed to be
The accepted answer misses top level files. This is the actual equivalent of 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)
Don't forget the for f in files loop, either. Similarly, remember to os.path.join(root, f) to get the full path.
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)
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')
use os.lchown instead of os.chown for changing link themselves and files together.
来源:https://stackoverflow.com/questions/2853723/what-is-the-python-way-for-recursively-setting-file-permissions