0

I would like to extract common path from a list irrespective of any case using python 2.7

I'm trying to use os.path.commonprefix() to extract the common prefix from the list but unable to extract the expected path due to case sensitive extraction. Is there any way to extract the common path by ignoring the case?

paths = ['C:\Users\Public\Desktop', 'c:\Users\Default']

prefix = os.path.commonprefix(paths)

I expect the output of prefix to be 'c:\Users\' or 'C:\Users\', but it returns an empty string because of case sensitive 'C:\' drive in paths

Dulaj Kulathunga
  • 1,248
  • 2
  • 9
  • 19
RaviG
  • 1
  • Unrelated to the problem, but when defining strings with backslashes, be sure to escape the backslashes or use raw strings. – glibdud Oct 08 '19 at 14:47
  • Standard warning: os.path.commonprefix doesn't do [what you think it does](https://stackoverflow.com/questions/21498939/how-to-circumvent-the-fallacy-of-pythons-os-path-commonprefix). – DSM Oct 08 '19 at 14:59

2 Answers2

0

The usual trick is to simply convert all the strings to a consistent case before comparing:

>>> os.path.commonprefix([path.lower() for path in paths])
'c:\\users\\'

If you really only want the first character to be case-insensitive:

>>> os.path.commonprefix([path[0].upper() + path[1:] for path in paths])
'C:\\Users\\'
glibdud
  • 7,550
  • 4
  • 27
  • 37
  • Thanks for your response but unfortunately it didn't solve my purpose. Actually, I would like extract common path and replace it with some string for a path in the list. So, converting the string into consistent case extracts common path but how to replace the common path alone without changing the case for rest of the path. – RaviG Oct 08 '19 at 17:28
  • @RaviG Can you elaborate? This returns exactly what you said you want. – glibdud Oct 08 '19 at 17:29
  • Here is an example: vob_root = "c:\Ivy\lib" abs_mk_path = "C:\Ivy\lib\ar-nw\Datalink\TestNw\NwD_Output\Src" paths = [vob_root, abs_mk_path] common_path = os.path.commonprefix(paths) mkpath = abs_mk_path.replace(common_path, '$(VOB_ROOT)') Expecting mkpath = $(VOB_ROOT)\ar-nw\Datalink\TestNw\NwD_Output\Src – RaviG Oct 08 '19 at 17:33
  • Yeah, that's something you should have included in the question if it's important. In that case, just convert all your paths to a consistent case in the first place (`paths = [path.lower() for path in paths]`) and go from there. – glibdud Oct 08 '19 at 17:36
  • Or rather, since you go back and recheck the original variables, do `vob_root = "...".lower()` and `abs_mk_path = "...".lower()`. – glibdud Oct 08 '19 at 17:43
0
import os
paths = [r'C:\Users\Public\Desktop', r'c:\Users\Default']

Run generous, case insensitive prefix search

prefix=os.path.commonprefix([path.lower() for path in paths])

Method 1:

then find first of all real paths corresponding to search results, if any prefix found

prefix=[path[:len(prefix)] for path in paths if path.lower().startswith(prefix)][0] if prefix!='' else ''
print(prefix)
#'C:\Users\'

Method 2:

index of any match with case insensitive search

index = next((i for i, path in enumerate(paths) if path.lower().startswith(prefix)), -1)

index of better match with case sensitive search, doesn't try if none found above

index = next((i for i, path in enumerate(paths) if path.startswith(prefix)), index) if index!=-1 else index
print(paths[index][:len(prefix)] if index!=-1 else '')
#'C:\Users\'