Find absolute path of a file in python when knowing the last part of the path and the base directory?

Viewed 363

Using python, I have the last parts of paths to existing files, like that:

sub_folder1/file1.txt
sub_folder2/file120.txt
sub_folder78/file99.txt

Note, that these paths are not the relative paths to the current folder I am working in, e.g., this pandas.read_csv('sub_folder1/file1.txt') would through a non-existing-file error. Nevertheless, I know all the files have the same base directory base_dir, but I don't know the absolute path. This means a file could be located like this:

base_dir/inter_folder1/sub_folder1/file1.txt

Or like this:

base_dir/inter_folder7/inter_folder4/.../sub_folder1/file1.txt

Is there a function that returns the absolute path, when given the last part of the path and the base directory of a file (or equivalently, finding the intermediate folders)? Should be looking like that:

absolut_path = some_func(end_path='bla/bla.txt', base_dir='BLAH')

I thought pathlib might have a solution, but couldn't find anything there. Thanks


I need this to do something like the below:

for end_path in list_of_paths:
    full_path = some_func(end_path=end_path, base_dir='base_dir')
    image = cv2.imread(full_path)
2 Answers

This should be fairly easy to implement from pathlib:

from pathlib import Path

def find(end_path: str, base_dir: str):
    for file in Path(base_dir).rglob("*"):
        if str(file).endswith(end_path):
            yield file

This is a generator, to match the pathlib interface; as such it will yield pathlib.PosixPath objects. It will also find all matching files, for example:

[str(f) for f in find(end_path="a.txt", base_dir="my_dir")]
# creates:
# ['my_dir/a.txt', 'my_dir/sub_dir/a.txt']

If you just want the first value you can just return the first item:

def find_first(end_path: str, base_dir: str):
    for file in Path(base_dir).rglob("*"):
        if str(file).endswith(end_path):
            return str(file)

abs_path = find_first(end_path="a.txt", base_dir="my_dir")

A better function that would improve the lookup:

from pathlib import Path

def find(pattern, suffixes, base_dir):
    for file in Path(base_dir).rglob(pattern):
        if any(str(file).endswith(suffix) for suffix in suffixes):
            yield str(file)

base_dir = "base_directory"
suffixes = [
    'sub_folder1/file1.txt', 
    'sub_folder2/file120.txt', 
    'sub_folder78/file99.txt',
]

for full_path in find(pattern="*.txt", suffixes=suffix, base_dir=base_dir):
    image = cv2.imread(full_path)

You need to search for the sub-folder within the base folder e.g,

import os
for dirpath, dirnames, files in os.walk(os.path.abspath(base_dir)):
    if dirpath.endswith(subfolder1):
        print(dirpath)

You might want to also make sure that the file exists in that folder using:

if dirpath.endswith("subfolder1") and "file1.txt" in files:
    print(dirpath)
Related