pythonpython-3.xobjectrecursion

Recursive Directory Search - Not getting the correct current working directory (Python)


I'm currently in the early stages of a course for Python, and have hit a wall and was hoping for some guidance. The problem states.

  1. -Write a function or method called find that takes two arguments called path and dir. The path argument should accept a relative or absolute path to a directory where the search should start, while the dir argument should be the name of a directory that you want to find in the given path. Your program should display the absolute paths if it finds a directory with the given name.
  2. The directory search should be done recursively. This means that the search should also include all subdirectories in the given path.

Example input: path="./tree", dir="python"

I wasnt able to solve it and finally took a look at the given answer but it doesnt seem to work correctly either

import os

class DirectorySearcher:
    def find(self, path, dir):
        try:
            os.chdir(path)
        except OSError:
            # Doesn't process a file that isn't a directory.
            return

        current_dir = os.getcwd()
        for entry in os.listdir("."):
            if entry == dir:
                print(os.getcwd() + "/" + dir)
            self.find(current_dir + "/" + entry, dir)


directory_searcher = DirectorySearcher()
directory_searcher.find("./tree", "python")

I created a few sample folders on my desktop and the expected output was

.../tree/python
.../tree/c/python

My output though is actually yielding

C:\Users\abc\Desktop\tree\c\python
C:\Users\abc\Desktop\tree\c\python\python

I had created the following folders

tree ------>c------>python
     ------>python

If I understand correctly, it looks like the code would first be able to pull up the folders [c, python]. It then goes into the c directory, finds the Python folder, tries to loop through that, and gets returned back to the next value in the list [python]. But at this point the current working directory is still the last one it traversed which is C:\Users\abc\Desktop\tree\c\python. Since the next value is [python] it just takes the last directory and tags on the [python] value at the end.

I been trying to make it work, but can't quite seem to wrap my head around how to fix this. Any help is much appreciated.


Solution

  • The problem is that returning from the recursion doesn't restore the working directory. You should do chdir("..") before returning.

    class DirectorySearcher:
        def find(self, path, dir):
            try:
                os.chdir(path)
            except OSError:
                # Doesn't process a file that isn't a directory.
                return
    
            current_dir = os.getcwd()
            for entry in os.listdir("."):
                if entry == dir:
                    print(os.getcwd() + "/" + dir)
                self.find(current_dir + "/" + entry, dir)
            os.chdir("..")
    

    Or you could avoid changing the directory in the first place. You can use os.path.isdir() to test if path is a directory.

    class DirectorySearcher:
        def find(self, path, dir):
            if not os.path.isdir(path):
                # Doesn't process a file that isn't a directory.
                return
    
            for entry in os.listdir(path):
                if entry == dir:
                    print(os.path.join(path, entry))
                self.find(os.path.join(path, entry), dir)
            os.chdir("..")
    

    In this version I've also replaced the filename concatenation with os.path.join().