如何规避Python的os.path.commonprefix的谬误?

blu*_*e10 18 python path prefix

我的问题是找到给定文件集的公共路径前缀.

从字面上看,我期待"os.path.commonprefix"可以做到这一点.不幸的是,commonprefix位于其中的事实path相当具有误导性,因为它实际上将搜索字符串前缀.

对我来说问题是,如何才能真正解决路径?在这个(相当高的评级)答案中简要提到了这个问题,但仅作为附注并且提议的解决方案(对commonprefix的输入附加斜线)imho存在问题,因为它将失败例如:

os.path.commonprefix(['/usr/var1/log/', '/usr/var2/log/'])
# returns /usr/var but it should be /usr
Run Code Online (Sandbox Code Playgroud)

为了防止其他人陷入同一个陷阱,可能值得在一个单独的问题中讨论这个问题:是否有一个简单/可移植的解决方案,不依赖于对文件系统的讨厌检查(即访问结果) commonprefix并检查它是否是一个目录,如果没有返回os.path.dirname结果)?

Dan*_* D. 12

前一段时间我遇到了这里os.path.commonprefix的字符串前缀,而不是预期的路径前缀.所以我写了以下内容:

def commonprefix(l):
    # this unlike the os.path.commonprefix version
    # always returns path prefixes as it compares
    # path component wise
    cp = []
    ls = [p.split('/') for p in l]
    ml = min( len(p) for p in ls )

    for i in range(ml):

        s = set( p[i] for p in ls )         
        if len(s) != 1:
            break

        cp.append(s.pop())

    return '/'.join(cp)
Run Code Online (Sandbox Code Playgroud)

它可以通过更换变得更便携'/'使用os.path.sep.

  • 这给出了文件或目录名称的合理答案,但在一般情况下,如果函数的结果是文件或目录名称而不做更多的工作(例如通过控制输入),则无法确定.另外,我相信这会返回与`os.path.dirname(os.path.commonprefix([p +'/'for p in l]))完全相同的结果. (3认同)

cja*_*jac 11

似乎在最近的Python版本中已经纠正了这个问题.版本3.5中的新功能是函数os.path.commonpath(),它返回公共路径而不是公共字符串前缀.

  • 谢谢!这是切换到 python 3 的另一个原因——很高兴我去年终于做到了。 (2认同)

Dan*_*etz 6

假设您需要公共目录路径,一种方法是:

  1. 仅使用目录路径作为输入.如果您的输入值是文件名,请调用os.path.dirname(filename)以获取其目录路径.
  2. "规范化"所有路径,使它们相对于同一个路径,并且不包括双分隔符.最简单的方法是调用os.path.abspath( )以获取相对于根的路径.(您可能还想使用os.path.realpath( )删除符号链接.)
  3. 在所有规范化目录路径的末尾添加一个最终分隔符(可以使用os.path.sep或移植os.sep).
  4. 呼吁os.path.dirname( )结果os.path.commonprefix( ).

在代码中(不删除符号链接):

def common_path(directories):
    norm_paths = [os.path.abspath(p) + os.path.sep for p in directories]
    return os.path.dirname(os.path.commonprefix(norm_paths))

def common_path_of_filenames(filenames):
    return common_path([os.path.dirname(f) for f in filenames])
Run Code Online (Sandbox Code Playgroud)