Search code examples
pythonpython-3.xpathlib

How to get a specific parent of a path by its name?


I have a function that returns the full path of a specific parent that I look for by a constant name. I am currently using os.path and strings for paths so right now this is done with regular-expressions.

What I want is for example for a constant parent = d to be able to get:

/a/b/c/d/e      -->  /a/b/c/d
/a/b/c/d/e/f    -->  /a/b/c/d
/root/a/b/c/d/e -->  /root/a/b/c/d

Note: as the example shows I don't want to rely on any fixed position from both sides.

I have tried 2 ways but both feels a bit clunky:

  1. Use the parts in order to find the correct parents element:

    >>> path = "/a/b/c/d/e/f"
    >>> parts = Path(path).parts
    >>> parent_index = len(parts) - 1 - parts.index('d') - 1
    >>> Path(path).parents[parent_index]
    PosixPath('/a/b/c/d')
    
  2. Use the parts and concatenate the relevant ones:

    >>> path = "/root/a/b/c/d/e"
    >>> parts = Path(path).parts
    >>> Path(*parts[:parts.index('d')+1])
    PosixPath('/root/a/b/c/d')
    

I would say that the second one seems reasonable, but still, my question is: Is there a more direct, pythonic way to achieve this? The repeated indexing and slicing of the parents feels inefficient and quite confusing.


P.S. In case the part is not present in the path it is enough to raise an exception or any indicator (right now I wrap the code with index above with a try/except).


Solution

  • You can use a while loop instead to keep searching backwards for a parent of the given name:

    path = Path("/a/b/c/d/e/f")
    while path.name != 'd':
        path = path.parent
        assert path.name, 'No parent found with the given name'
    print(path)
    

    This outputs:

    /a/b/c/d