3

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:
Riad
  • 953
  • 3
  • 13
  • 23

2 Answers2

6

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)
mgilson
  • 300,191
  • 65
  • 633
  • 696
0

Here is the code I eneded up writing with @mgilson asvice

import os
import glob
# Function to find the file
def find(filename, path):
  for root, dirs, files in os.walk(path):
    if filename in files:
      yield os.path.join(root, filename)

# Python boiler plate call.
if __name__ == "__main__":
  # build path expression
  projectUserSimDirs=os.environ['LINUX_VAR']+'/path/to/one/*/dir/and/*/and/*'
  # traverse the path
  for result in glob.iglob(projectUserSimDirs):
    # Check is it is a valid dir
    if os.path.isdir(result):
      # Search for files
      for filename in find('myFile.txt', result):
        print(filename)

Feel free to append

Riad
  • 953
  • 3
  • 13
  • 23