我获得了检查文件所需的路径列表。当然,如果给我一个root和一个子目录,则不需要处理子目录。例如
c:\test // process this
c:\test\pics // do not process this
c:\test2 // process this
如何判断(跨平台)路径不是另一个路径的子目录。最好是我希望这是跨平台的,并且我不担心符号链接,只要它们不是循环的(更糟糕的是我最终处理数据两次)。
更新:这是我最终使用的代码,感谢@ F.J
def unique_path_roots(paths):
visited = set()
paths = list(set(paths))
for path in sorted(paths,key=cmp_to_key(locale.strcoll)):
path = normcase(normpath(realpath(path)))
head, tail = os.path.split(path)
while head and tail:
if head in visited:
break
head, tail = os.path.split(head)
else:
yield path
visited.add(path)
答案 0 :(得分:8)
def is_subdir(path, directory):
path = os.path.realpath(path)
directory = os.path.realpath(directory)
relative = os.path.relpath(path, directory)
if relative.startswith(os.pardir):
return False
else:
return True
答案 1 :(得分:6)
我会维护一组你已经处理过的目录,然后对每个新路径进行检查,看看在处理之前它的任何父目录是否已存在于该集合中:
import os.path
visited = set()
for path in path_list:
head, tail = os.path.split(path)
while head and tail:
if head in visited:
break
head, tail = os.path.split(head)
else:
process(path)
visited.add(path)
请注意,应对path_list
进行排序,以便子目录始终位于其父目录之后(如果存在)。
答案 2 :(得分:2)
跟踪您已经处理过的目录(以规范化形式),如果您已经看过它们,请不要再次处理它们。这样的事情应该有效:
from os.path import realpath, normcase, sep
dirs = [r"C:\test", r"C:\test\pics", r"C:\test2"]
processed = []
for dir in dirs:
dir = normcase(realpath(dir)) + sep
if not any(dir.startswith(p) for p in processed):
processed.append(dir)
process(dir) # your code here
答案 3 :(得分:0)
修正和简化的jgoeders版本:
def is_subdir(suspect_child, suspect_parent):
suspect_child = os.path.realpath(suspect_child)
suspect_parent = os.path.realpath(suspect_parent)
relative = os.path.relpath(suspect_child, start=suspect_parent)
return not relative.startswith(os.pardir)
答案 4 :(得分:0)
这是我提出的is_subdir
效用函数。
bytes
和str
,匹配os.path
,同时支持两者。)os.path.relpath
,如果路径位于不同的驱动器上,则会在ms-windows上引发异常。 (C:\foo
- > D:\bar
)代码:
def is_subdir(path, directory):
"""
Returns true if *path* in a subdirectory of *directory*.
"""
import os
from os.path import normpath, normcase, sep
path = normpath(normcase(path))
directory = normpath(normcase(directory))
if len(path) > len(directory):
sep = sep.encode('ascii') if isinstance(directory, bytes) else sep
if path.startswith(directory.rstrip(sep) + sep):
return True
return False