1

I made a function that searches files recursively and I want it to stop recursion when the first file is found:

def search_file(path):
    for name in os.listdir(path):
        sub = os.path.join(path, name)
        if os.path.isfile(sub):
            return sub#And break recursion
        else:
            search_file(sub)
Vincent Savard
  • 34,979
  • 10
  • 68
  • 73

4 Answers4

2

Return a flag that says whether the file was found. When you call search_file, return if the return value is True.

Neil G
  • 32,138
  • 39
  • 156
  • 257
2

You are close. You already break recursion when you find the file, the problem is that you didn't propegate that result all the way up the chain. A well-placed print statement would show what went wrong.

import os

def search_file(path):
    for name in os.listdir(path):
        sub = os.path.join(path, name)
        print('peek at: {}'.format(sub))
        if os.path.isfile(sub):
            return sub#And break recursion
        else:
            sub = search_file(sub)
            if sub:
                return sub  
print(search_file('a'))
tdelaney
  • 73,364
  • 6
  • 83
  • 116
0

Note that you need to be able to return a false entry in case it loops all the way down without finding anything. However, you do not want to break out of the for loop if nothing found in one subdirectory without checking the next sub directory. The return will break out of the function, returning the results without having to enter a break.

def search_file(path):
    Initialize results to no file found
    val = False
    sub = None
    for name in os.listdir(path):
        sub = os.path.join(path, name)
        val = os.path.isfile(sub):
        if val:
            return val, sub #And break recursion
        else:
            #check the subdirectory.
            val, sub = search_file(sub)
            # Break out if a valid file was found.
            if val:
                return val, sub
    # No files found for this directory, return a failure
    return val, sub

On the other hand, if you want to have only one return, you can use a break as follows

def search_file(path):
    Initialize results to No file found
    val = False
    sub = None
    for name in os.listdir(path):
        sub = os.path.join(path, name)
        val = os.path.isfile(sub):
        if val:
            break # break out of the for loop and return
        else:
            #check the subdirectory.
            val, sub = search_file(sub)
            # Break out if a valid file was found.
            if val:
                break
    # Return the True or False results
    return val, sub
sabbahillel
  • 4,357
  • 1
  • 19
  • 36
0

I see a problem of not being able to return a value other than None once into the else: statement. Could you provide broader details describing what you are trying to do?

There is no way to simply exit recursion when you accomplish a task. Each recursive step that was opened must be closed before moving on. The function must return something (None or a value) to its caller.

I'm imagining this being a class method that sets value to an attribute because it doesn't return anything once recursion has begun. Here's what I would do in the instance that this is a class method.

def search_file(self, path):
    for name in os.listdir(path):
        sub = os.path.join(path, name)
        if os.path.isfile(sub):
            self.random_attr = sub
            return True  #And break recursion
        elif search_file(sub):
            break
A Magoon
  • 1,180
  • 2
  • 13
  • 21