如何在Python中一次性修改嵌套目录的权限?
问题
我目前通过以下代码逐个修改嵌套目录(例如路径/apps/sys/utils/prod/sales/apparel/)的权限。请问能否一次性完成权限修改,达到与循环逐个修改相同的效果?
import os import stat def change_permissions(path, new_mode): """Change permissions of the directory to new_mode.""" if not os.path.islink(path): original_mode = os.stat(path).st_mode os.chmod(path, new_mode) oct_perm = oct(new_mode) unix_perm = oct_perm[-3: (len(oct_perm))] print(f"Permission of {path} changed to {new_mode} = {unix_perm}") return original_mode return None target_full_path = "/apps/sys/utils/prod/sales/apparel/shirts.csv" # Determine the directory path up to which permissions need to be changed target_dir = os.path.dirname(target_full_path) print(f"The abstract file dir path upto which perm to be changed {target_dir}") # Change permissions for the specific directory needed original_permissions = [] current_dir = "/apps/sys/utils/prod" for part in target_dir.split(os.sep)[len(dest_root.split(os.sep)):]: current_dir = os.path.join(current_dir, part) print(f"\n### part = {part} and current_dir = {current_dir}") if not os.path.exists(current_dir): os.makedirs(current_dir) print(f"Created the current_dir = {current_dir}") original_mode = change_permissions(current_dir, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) original_permissions.append((current_dir, original_mode)) print (f"Original mode for current_dir ({current_dir}) is {original_mode}\n")
回答
可以一次性完成权限修改,以下是两种实现方式,效果和你当前的循环逻辑完全一致:
方式一:用os.walk反向遍历目录层级
os.walk可以遍历目录树,反向遍历就能从最深层的子目录往上处理,一次性完成所有目标目录的权限修改,同时保留原权限记录:
import os import stat def change_permissions(path, new_mode): """Change permissions of the directory to new_mode.""" if not os.path.islink(path): original_mode = os.stat(path).st_mode os.chmod(path, new_mode) oct_perm = oct(new_mode) unix_perm = oct_perm[-3:] print(f"Permission of {path} changed to {new_mode} = {unix_perm}") return original_mode return None target_full_path = "/apps/sys/utils/prod/sales/apparel/shirts.csv" target_dir = os.path.dirname(target_full_path) current_root = "/apps/sys/utils/prod" original_permissions = [] # 反向遍历目录树,从最底层子目录开始处理 for root, dirs, files in os.walk(current_root, topdown=False): # 只处理current_root到target_dir之间的目录 if root.startswith(target_dir) and root != current_root: print(f"\n### Processing directory: {root}") original_mode = change_permissions(root, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) original_permissions.append((root, original_mode)) print(f"Original mode for {root} is {original_mode}\n") # 额外处理target_dir本身(确保覆盖到最终目录) if target_dir not in [item[0] for item in original_permissions]: print(f"\n### Processing directory: {target_dir}") original_mode = change_permissions(target_dir, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) original_permissions.append((target_dir, original_mode)) print(f"Original mode for {target_dir} is {original_mode}\n")
方式二:创建目录时直接指定权限(针对新建目录场景)
如果你的代码中很多目录是通过os.makedirs新建的,可以直接在创建时指定权限,避免后续逐个修改:
import os import stat def change_permissions(path, new_mode): """Change permissions of the directory to new_mode.""" if not os.path.islink(path): original_mode = os.stat(path).st_mode os.chmod(path, new_mode) oct_perm = oct(new_mode) unix_perm = oct_perm[-3:] print(f"Permission of {path} changed to {new_mode} = {unix_perm}") return original_mode return None target_full_path = "/apps/sys/utils/prod/sales/apparel/shirts.csv" target_dir = os.path.dirname(target_full_path) current_root = "/apps/sys/utils/prod" original_permissions = [] # 新建目录时直接指定权限,0o777对应stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO if not os.path.exists(target_dir): os.makedirs(target_dir, mode=0o777, exist_ok=True) print(f"Created directory tree: {target_dir} with permissions 0o777") # 处理已存在的目录(如果有的话) for root, dirs, files in os.walk(current_root, topdown=False): if root.startswith(target_dir) and root != current_root: print(f"\n### Processing existing directory: {root}") original_mode = change_permissions(root, 0o777) original_permissions.append((root, original_mode)) print(f"Original mode for {root} is {original_mode}\n")
注意事项
- 两种方式都会保留原权限的记录,和你原代码的
original_permissions列表功能一致 - 如果目录是符号链接,都会跳过处理,和原逻辑对齐
- 方式一适合处理已存在的目录树,方式二更适合需要新建目录的场景
内容的提问来源于stack exchange,提问作者A.G.Progm.Enthusiast
相关产品推荐
相关产品推荐

