When dealing with windows paths on a *nix system sometimes youll need to resolve case insensitive paths. While using a fat filesystem or making everything lowercase would work. this function means you can get python to take a case insensitive path and return the path with the correct case (if it exists).
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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | def getCaseInsensitivePath(path, RET_FOUND=False):
'''
Get a case insensitive path on a case sensitive system
RET_FOUND is for internal use only, to avoid too many calls to os.path.exists
# Example usage
getCaseInsensitivePath('/hOmE/mE/sOmEpAtH.tXt')
'''
import os
if path=='' or os.path.exists(path):
if RET_FOUND: ret = path, True
else: ret = path
return ret
f = os.path.basename(path) # f may be a directory or a file
d = os.path.dirname(path)
suffix = ''
if not f: # dir ends with a slash?
if len(d) < len(path):
suffix = path[:len(path)-len(d)]
f = os.path.basename(d)
d = os.path.dirname(d)
if not os.path.exists(d):
d, found = getCaseInsensitivePath(d, True)
if not found:
if RET_FOUND: ret = path, False
else: ret = path
return ret
# at this point, the directory exists but not the file
try: # we are expecting 'd' to be a directory, but it could be a file
files = os.listdir(d)
except:
if RET_FOUND: ret = path, False
else: ret = path
return ret
f_low = f.lower()
try: f_nocase = [fl for fl in files if fl.lower() == f_low][0]
except: f_nocase = None
if f_nocase:
if RET_FOUND: ret = os.path.join(d, f_nocase) + suffix, True
else: ret = os.path.join(d, f_nocase) + suffix
return ret
else:
if RET_FOUND: ret = path, False
else: ret = path
return ret # cant find the right one, just return the path as is.
|
why would you want that? and what if there are multiple matches?
Without commenting on the recipe itself, I'd remove the RET_FOUND parameter (that makes the whole thing look ugly). Use a helper function that always returns a tuple (path, boolean) and a public function that calls the former (and returns only the first component).
Also, when there are several alternative names, I'd either return all matches or raise an exception ("In the face of ambiguity, refuse the temptation to guess." and "Errors should never pass silently.")
This script was used for importing data from a windows system which has case insensitive image file references. Looking at the code now there are some improvements I'd make to it, such as multiple returns, but in the case where you receive a lot of cross linked files from a windows system. this generally isn't a problem.