Welcome, guest | Sign In | My Account | Store | Cart

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).

Python, 56 lines
 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.

3 comments

Florian Mayer 13 years ago  # | flag

why would you want that? and what if there are multiple matches?

Gabriel Genellina 12 years, 6 months ago  # | flag

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.")

Campbell Barton (author) 11 years, 6 months ago  # | flag

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.