Simply call lower to make the string lowercase before calling endswith:
ext = (".dae", ".xml", ".blend", ".bvh", ".3ds", ".ase",
".obj", ".ply", ".dxf", ".ifc", ".nff", ".smd",
".vta", ".mdl", ".md2", ".md3"
".pk3", ".mdc", ".x"
".q3o", ".q3s", ".raw"
".ac", ".dxf", ".irrmesh"
".irr", ".off", ".ter"
".mdl", ".hmp", ".mesh.xml"
".skeleton.xml", ".material", ".ms3dv"
".lwo", ".lws", ".lxo"
".csm", ".cob", ".scn"
".xgl", ".zgl")
for folder, subfolders, filename in os.walk(directory):
if any([filename.lower().endswith(tuple(ext)) for filename in filenames]):
Answer from javidcf on Stack OverflowSimply call lower to make the string lowercase before calling endswith:
ext = (".dae", ".xml", ".blend", ".bvh", ".3ds", ".ase",
".obj", ".ply", ".dxf", ".ifc", ".nff", ".smd",
".vta", ".mdl", ".md2", ".md3"
".pk3", ".mdc", ".x"
".q3o", ".q3s", ".raw"
".ac", ".dxf", ".irrmesh"
".irr", ".off", ".ter"
".mdl", ".hmp", ".mesh.xml"
".skeleton.xml", ".material", ".ms3dv"
".lwo", ".lws", ".lxo"
".csm", ".cob", ".scn"
".xgl", ".zgl")
for folder, subfolders, filename in os.walk(directory):
if any([filename.lower().endswith(tuple(ext)) for filename in filenames]):
This is a really old answer but since Python 3.3, there exists the casefold() method which is more aggressive than lower() and is the more natural caseless string matching. So something like the following is an option:
filename.casefold().endswith(ext)
On a tangential note, any() short-circuits, meaning it stops at the first True, so it is much faster if any() is called on a generator expression instead of a list (especially if the matching string is towards the beginning of a long list) because with genexpr, we can stop the endswith check right away while with list, we have to perform the endswith check for every string before the any() evaluation.
So instead of
any([filename.lower().endswith(ext) for filename in filenames])
# ^ ^ <--- list
use
any(filename.lower().endswith(ext) for filename in filenames)
# ^ ^ <--- genexpr
Finally, since this question is tagged regex, here's a regex solution as well. Simply compile a pattern that ignores case and search whether the pattern matches.
import re
pat = re.compile(fr"({'|'.join(re.escape(e) for e in ext)})$", re.I)
for folder, subfolders, filenames in os.walk('.'):
if any(pat.search(filename) for filename in filenames):
# do something
You could use a regular expression as follows:
In [33]: bool(re.match('he', 'Hello', re.I))
Out[33]: True
In [34]: bool(re.match('el', 'Hello', re.I))
Out[34]: False
On a 2000-character string this is about 20x times faster than lower():
In [38]: s = 'A' * 2000
In [39]: %timeit s.lower().startswith('he')
10000 loops, best of 3: 41.3 us per loop
In [40]: %timeit bool(re.match('el', s, re.I))
100000 loops, best of 3: 2.06 us per loop
If you are matching the same prefix repeatedly, pre-compiling the regex can make a large difference:
In [41]: p = re.compile('he', re.I)
In [42]: %timeit p.match(s)
1000000 loops, best of 3: 351 ns per loop
For short prefixes, slicing the prefix out of the string before converting it to lowercase could be even faster:
In [43]: %timeit s[:2].lower() == 'he'
1000000 loops, best of 3: 287 ns per loop
Relative timings of these approaches will of course depend on the length of the prefix. On my machine the breakeven point seems to be about six characters, which is when the pre-compiled regex becomes the fastest method.
In my experiments, checking every character separately could be even faster:
In [44]: %timeit (s[0] == 'h' or s[0] == 'H') and (s[1] == 'e' or s[1] == 'E')
1000000 loops, best of 3: 189 ns per loop
However, this method only works for prefixes that are known when you're writing the code, and doesn't lend itself to longer prefixes.
How about this:
prefix = 'he'
if myVeryLongStr[:len(prefix)].lower() == prefix.lower()
You can assert that if you start at the end of each string and match them character by character, at least one of the strings will be exhausted without any differences:
def either_endswith(a, b):
return all(a_char == b_char for a_char, b_char in zip(reversed(a), reversed(b)))
def either_endswith_case_insensitive(a, b):
return either_endswith(a.lower(), b.lower())
# Positive
either_endswith_case_insensitive('aaaa', 'a')
either_endswith_case_insensitive('a', 'aaaa')
either_endswith_case_insensitive('aaaa', 'A')
either_endswith_case_insensitive('BbbB', 'BBbb')
# Negative
either_endswith_case_insensitive('aaaa', 'c')
either_endswith_case_insensitive('a', 'ccccc')
def end_other(a, b):
if a[-len(b):].lower()==b.lower() or b[-len(a):].lower()==a.lower():
return True
return False