Normally, I wouldn't give a full solution because this smells like homework (which is also why I'm avoiding os.walk
), but since you have posted your attempt, here's an explanation and a solution:
For one thing, every time you call findAll
, you initialize lst
. Sure, you return it at the end, but you don't do anything with the return value, so the effect lst.append
is contained within the recursion and is therefore not visible outside. Let me try to draw diagram to explain this (with one level of recursion):
+--------------------------------------------------+
|Outer Level: |
| |
|`lst = []` |
|found file f1 with name fname |
|`lst.append(f1)` |
|+------------------------------------------------+|
||Inner Level ||
|| ||
||`lst=[]` ||
||found file f2 with name fname ||
||`lst.append(f2)` ||
||`return lst` ||
|+------------------------------------------------+|
|a list is returned from recursive call, |
|but not assigned to a variable. |
|Therefore, `lst` remains unchanged |
+--------------------------------------------------+
There are a couple of ways by which you can fix this:
- move
lst
to a scope outside findAll
(personally, this is what I would do)
- use the return value from the recursive call to modify
lst
move lst
to a scope outside findAll
lst= []
def findAll(fname, path):
global lst
for item in os.listdir(path):
n = os.path.join(path, item)
try: # really though, you don't need to use try/except here
if item == fname:
lst.append(n)
else:
findAll(fname,n)
except:
pass
After findAll
has terminated, lst
will contain the values you want
use the return value from the recursive call to modify lst
def findAll(fname, path, answer=None):
if answer == None:
answer = []
for item in os.listdir(path):
n = os.path.join(path, item)
try:
if item == fname:
answer += [n]
except:
findAll(fname,n, answer)
return answer
Hope this helps
PS: of course, the non-homework way to do this would be to use os.walk
:
answer = []
def findAll(fname, dirpath):
dirpath, dirnames, filenames = os.walk(dirpath)
for filename in filenames:
if filename == fname:
answer.append(os.path.join(dirpath, filename))
for dirname in dirnames:
findAll(fname, os.path.join(dirpath, dirname))
# now, answer contains all the required filepaths
EDIT: OP asked for a version that doesn't use global variables:
def findAll(fname, root, answer=None):
if answer == None:
answer = []
for entry in os.listdir(root):
if os.path.isdir(os.path.join(root, entry)):
answer += findAll(fname, os.path.join(root, entry))
else:
if entry == fname:
answer.append(os.path.join(root, entry))
return answer