在Python中删除除一个子目录以外的目录
我有一些目录,我想删除,但其中一个目录有一个子目录,我想保留 例如: 档案 照片 cat.png icon.png 音乐 song.mp3 电影 第一.mp4 我想删除除子目录图片以外的所有内容(目录和子目录) 现在我有这个:在Python中删除除一个子目录以外的目录,python,Python,我有一些目录,我想删除,但其中一个目录有一个子目录,我想保留 例如: 档案 照片 cat.png icon.png 音乐 song.mp3 电影 第一.mp4 我想删除除子目录图片以外的所有内容(目录和子目录) 现在我有这个: def Destroy_Path(path): shutil.rmtree(path, ignore_errors=True) 这里有一个解决方案未经测试 请注意,使用os.walk()可以就地更改dirnames,告诉它不要递归到子目录中,并避免使用会破坏此功
def Destroy_Path(path):
shutil.rmtree(path, ignore_errors=True)
这里有一个解决方案未经测试强> 请注意,使用
os.walk()
可以就地更改dirnames
,告诉它不要递归到子目录中,并避免使用会破坏此功能的top down=False
:
当topdown为True
时,调用者可以就地修改目录名列表
(可能使用del
或slice赋值)和walk()
只会重复出现
进入名称保留为dirnames的子目录;这可能是
用于删除搜索,[…]
当自上而下为False时修改dirnames对漫游行为没有影响,因为在自下而上模式下,dirnames中的目录是在dirpath本身生成之前生成的
有关更多信息,请参阅
另外值得注意的是使用os.path.samefile()
进行路径比较。这是
这是未经测试的
使用风险自负强>
说真的,小心点强>
将图片
移动到其他地方,删除所有内容,然后将其移回。您是否接受任何标准的*nix工具,例如基于查找的解决方案?@Selcuk移动、删除和移回将不起作用,因为中间目录将同时被删除。可以为每个要保留的文件/文件夹重新创建所需的目录结构,但中间目录的元数据(如权限和修改日期)可能已丢失。这似乎有点过分了。只需定义一个小函数,将您感兴趣的每个文件夹从当前路径移动到临时目录,使用shutil.rmtree,然后将其移回,或者更好的是,打开Nautilus即可。@AlexanderHuszagh moving,删除和向后移动将不起作用,因为中间目录将同时被删除。可以为每个“受保护”项目重新创建所需的目录结构,但这些目录的元数据(如权限和修改日期)将丢失。这是解决复杂、全面问题的一个很好的解决方案。但除非这是一种非常不寻常的情况(比如远程日志,有人需要对dir进行写访问,但不需要读访问;有人需要对父级进行读访问,但不需要写),否则简单性在其他情况下也同样适用。如果他们需要匹配给定的文件名(可能在目录层次结构的任何级别),那么walk方法是很好的。@AlexanderHuszagh您建议的“简单”解决方案实际上并不简单:至少,它必须检查每个异常是否真的存在,将其移动到临时目录,调用rmtree()。
import os
def gen_dir_paths_except(base_path, exceptions):
# behave like os.walk(): return nothing if the given path isn't a directory
if not os.path.isdir(base_path):
return
# keep only existing paths in exceptions, so that os.path.samefile() works
exceptions = list(filter(os.path.exists, exceptions))
# don't forget the base directory
if any(os.path.samefile(base_path, x) for x in exceptions):
return
yield base_path
for curr_dirpath, dirnames, filenames in os.walk(base_path):
# skip directories mentioned in exceptions
dirnames_to_skip = []
for dir_name in dirnames:
dir_path = os.path.join(curr_dirpath, dir_name)
if any(os.path.samefile(dir_path, x) for x in exceptions):
dirnames_to_skip.append(dir_name)
else:
yield dir_path
for dir_name in dirnames_to_skip:
dirnames.remove(dir_name)
def rmtree_except(path, exceptions):
# Check that the path is actually a directory. This is needed here
# because os.walk() will silently return nothing for a non-directory.
if not os.path.isdir(path):
if not os.path.exists(path):
raise OSError("No such directory: " + path)
else:
raise OSError("Not a directory: " + path)
# keep only existing paths in exceptions, so that os.path.samefile() works
exceptions = list(filter(os.path.exists, exceptions))
dirs = list(gen_dir_paths_except(path, exceptions))
# iterate through directories in bottom-up order
for dir_path in reversed(dirs):
filenames = [
x for x in os.listdir(dir_path)
if not os.path.isdir(os.path.join(dir_path, x))
]
for file_name in filenames:
# skip files mentioned in exceptions
file_path = os.path.join(dir_path, file_name)
if not any(os.path.samefile(file_path, x) for x in exceptions):
os.remove(file_path)
try:
os.rmdir(dir_path)
except OSError: # directory not empty
pass # just leave the directory