Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

os.walk a path with wildcard

I would like to traverse a directory and search for a given file. Here is some code I wrote:

import os
def find(filename, path):
  for root, dirs, files in os.walk(path):
    for file in files:
      if file==filename:
        print(os.path.join(root, file))

# Python boiler plate call.
if __name__ == "__main__":
  find('myFile.txt', '/path/to/one/user/dir/and/subDir1/and/subDir2')

The above works pretty well.

Question1: How to improve my code to work with something like this:

  find('myFile.txt', '/path/to/one/*/dir/and/*/and/*')

Question2: What is the Pythonic way for:

      if file==filename:
like image 549
Riad Avatar asked Sep 19 '25 15:09

Riad


1 Answers

Regarding question1:

You're asking about a glob expression. Note that the expression you've posted isn't necessarily unique, so it could match multiple directories (and files). To get those files/directories, you can use the glob module

import glob
for result in glob.iglob('/path/to/one/*/dir/and/*/and/*'):
    find('myFile.txt', result)

I suppose that you may want to check that result is a directory before trying to find a file in it... (os.path.isdir(result))


Regarding question 2:

I think you probably just want to know if the file you are looking for is in files and then print/yield the full path:

def find(filename, path):
  for root, dirs, files in os.walk(path):
    if filename in files:
      print(os.path.join(root, filename))

There is nothing "unpythonic" about writing if x == y -- It's actually quite common. However, in your case, you didn't really need to do it. The pythonic thing is to use builtin operators to look for the object you want in the list and simply construct the output based on whether you found something or not. Also, I hinted at it above, but it's often nicer (and more re-useable) to yield the results instead of just printing them:

def find(filename, path):
  for root, dirs, files in os.walk(path):
    if filename in files:
      yield os.path.join(root, filename)

Now, you can print it in the caller (or do other things with it...):

for filename in find(needle, haystack):
  print(filename)
like image 189
mgilson Avatar answered Sep 22 '25 03:09

mgilson