Search code examples
pythonpathlib

comparing pathlib.Paths finding if one is a subdir of the other


How can I find out if a pathlib.Path() is a subdir of another?

I can take the string of pathlib.PurePath(), but it only works if I have the whole path.

with zipfile.ZipFile(fname, 'w') as zip:
  for f in files:
    myrelroot = relroot # relative root for this zipfile
    if f"{pathlib.PurePath(relroot)}" not in f"{pathlib.PurePath(f)}":
      myrelroot = None # outside of zipfile so we do not get ..\\..
    try:
      zip.write(f, arcname=os.path.relpath(f, myrelroot))
    except FileNotFoundError as e:
      log.warning(f"file '{f}' not found: {e}")
    else:
      log.info(f"adding {f} to {fname}")

Solution

  • You can use the pathlib methods is_relative_to and relative_to to determine if 1 path is contained within another as well as what that relative path is.

    >>> from pathlib import Path
    >>> base = Path('/home/username')
    >>> p1 = Path('/home/username/Downloads')
    >>> p2 = Path('/usr/bin')
    >>> p1.is_relative_to(base)
    True
    >>> p2.is_relative_to(base)
    False
    

    Then you can restructure your code to something like:

    from pathlib import Path
    
    fname = Path("some/path/to/zipfile.zip")
    relroot = fname.parent
    
    with zipfile.ZipFile(fname, 'w') as zip:
      for f in files:
        f = Path(f)
        if not f.exists(): # guard clause protects against non-existent files
            log.warning(f"file '{f}' not found: {e}")
            continue
    
        # default to use full path
        #   use relative f is a subdirectory of `relroot`
        arcname = f.resolve() 
        if f.is_relative_to(relroot):
            arcname = f.relative_to(relroot)
        
        zip.write(f, arcname=arcname)
        log.info(f"adding {f} to {fname}")