os.path.commonprefix () e os.path.relpath () são seus amigos:
>>> print os.path.commonprefix(['/usr/var/log', '/usr/var/security'])
'/usr/var'
>>> print os.path.commonprefix(['/tmp', '/usr/var']) # No common prefix: the root is the common prefix
'/'
Assim, você pode testar se o prefixo comum é um dos caminhos, ou seja, se um dos caminhos é um ancestral comum:
paths = […, …, …]
common_prefix = os.path.commonprefix(list_of_paths)
if common_prefix in paths:
…
Você pode encontrar os caminhos relativos:
relative_paths = [os.path.relpath(path, common_prefix) for path in paths]
Você pode até manipular mais de dois caminhos, com esse método, e testar se todos os caminhos estão todos abaixo de um deles.
PS : dependendo da aparência de seus caminhos, primeiro você deve executar alguma normalização (isso é útil em situações em que não se sabe se elas sempre terminam com '/' ou não, ou se alguns deles são relativos). Funções relevantes incluem os.path.abspath () e os.path.normpath () .
PPS : como Peter Briggs mencionou nos comentários, a abordagem simples descrita acima pode falhar:
>>> os.path.commonprefix(['/usr/var', '/usr/var2/log'])
'/usr/var'
mesmo que não/usr/var
seja um prefixo comum dos caminhos. Forçar todos os caminhos a terminarem com '/' antes de chamar resolve esse problema (específico).commonprefix()
PPPS : como o bluenote10 mencionou, a adição de uma barra não resolve o problema geral. Aqui está sua pergunta seguinte: Como contornar a falácia do os.path.commonprefix do Python?
PPPPS : a partir do Python 3.4, temos o pathlib , um módulo que fornece um ambiente de manipulação de caminhos mais saudável . Eu acho que o prefixo comum de um conjunto de caminhos pode ser obtido obtendo todos os prefixos de cada caminho (com PurePath.parents()
), fazendo a interseção de todos esses conjuntos pai e selecionando o prefixo comum mais longo.
PPPPPS : Python 3.5 introduziu uma solução adequada para esta pergunta :,os.path.commonpath()
que retorna um caminho válido.