问题
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?
回答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.
回答2:
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
回答3:
try os.path.join(root,momo)
that will give you full path
回答4:
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
回答5:
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)
回答6:
Don't forget the for f in files
loop, either. Similarly, remember to os.path.join(root, f)
to get the full path.
回答7:
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)
回答8:
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')
回答9:
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