Given search paths separated by a separator, find the first file that matches a given specification.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | from os.path import exists, join
from os import pathsep
from string import split
def search_file(filename, search_path):
"""Given a search path, find file
"""
file_found = 0
paths = string.split(search_path, pathsep)
for path in paths:
if exists(join(path, filename)):
file_found = 1
break
if file_found:
return abspath(join(path, filename))
else:
return None
if __name__ == '___main__':
search_path = '/bin' + pathsep + '/usr/bin' # ; on windows, : on unix
find_file = search_file('ls',search_path)
if find_file:
print "File found at %s" % find_file
else:
print "File not found"
|
Tags: sysadmin
Variation: Finding files on the Python path. Larger Python applications consist of sets of Python packages and associated sets of "resource" files (e.g. Glade project files, SQL templates, image files). It's convenient to store these associated files together with the Python packages which use them. It's easy to do so if you use a variation on this recipe, one which finds files relative to the Python path.
Mitch Chapman
Small correction. The call to string.split(), in the search_file() function, should just be a call to split() since the example uses 'from string import split'.
Another one. The abspath function is not imported. The first import statement should probably be 'from os.path import exists, join, abspath'.
Sometimes there are implicit extension on sought files. Here's a version that accommodates for implicit extensions (nice formatting system!)::
Hello. Hi! I try to use this search code :
!/usr/bin/python
from os.path import exists, join from os import pathsep from string import split
def search_file(filename, search_path): """Given a search path, find file """ file_found = 0 paths = string.split(search_path, pathsep) for path in paths: if exists(join(path, filename)): file_found = 1 break if file_found: return abspath(join(path, filename)) else: return None
if __name__ == '___main__': search_path = '/bin' + pathsep + '/usr/bin' # ; on windows, : on unix find_file = search_file('ls',search_path) if find_file: print "File found at %s" % find_file else: print "File not found
But where i must put the word to search ???? and How can i do to download the file found ???
The example provided are rather verbose. This is much simpler;
@Donovan - you had a couple of typo's in your code. Here's a simple version that is tested (I didn't need the extensions in my case, so I removed that):
def find_in_path(file_name): path = os.environ['PATH'] for d in path.split(os.pathsep): file_path = os.path.abspath(os.path.join(d, file_name)) if os.path.exists(file_path): return file_path return file_name
To point out one of those typos mentioned: os.environ('PATH') os.environ is a dict(), not a function. Calling it with parens () will raise an exception.
Also, because os.environ is a dict() type, os.environ['PATH']" will only work if the key which equals 'PATH' and the operating system's environment variable Path have the same case, that is upper() in this case. My MS Windows XP path environment varible did not work with the above examples because my OS returns "Path" as that key in os.environ and not "PATH".
It's likely more robust to use S = os.getenv('PATH'). And then use L = S.split(os.pathsep) or combine them into path = os.getenv('PATH').split(os.pathsep). os.getenv() to account for case issues.
If you might use this file search routing in some os.spawn, subprocess or multiprocess calls (as searching routines like this can really "block" [look it up]) consider two things.
One, there is a security risk if you do os.access() with a context manager (ie with file.open() as f:). See docs. This might be the case where you use this file search routine with some other file manipulation routine, like during an os.path.walk() or sum such thing.
And two, if you run spawn or subprocess or multiprocess and use options that do not carry over the environment varibles into the new process there will not be a PATH operating system environment varible at all. And you won't find your file and likely raise an exception.
To add a little more protection in these cases use os.getenv()'s second parameter, the "default" value; like this: os.getenv('PATH', os.defpath).
If you might use this filename search routine in an iterator, generator or os.path.walk()-like function you might want to include the current and parent paths in the beginning of the search; like this: os.curdir + os.pathsep + os.pardir + os.pathsep
Putting that logic together into a neat little function you get:
I believe you may need to modify either a line in the function:
if dir == r"C:\bin" and
if name == 'myprog' and
if ext == 'exe' and
if full == os.path.join(dir, name) + ext
then print full does
r"C:\bin\myprogexe"
and not r"C:\bin\myprog.exe"
So you could do:
Or you may need to modify the format expected of the exts function argument.
Consider:
So that you get "myprog.exe" and not "myprogexe"