How can I check a filename suffix against a lot of options tersely?
Question:
I’m trying to write a program that essentially divides different file types among different directories. My computer does have many different image file types, so it makes a very long line in my code:
if file.name.endswith(".jpg") or
file.name.endswith(".JPG") or
file.name.endswith(".jpeg") or
file.name.endswith(".JPEG") or
file.name.endswith(".heic") or
file.name.endswith(".HEIC") or
file.name.endswith(".png") or
file.name.endswith(".PNG") or
file.name.endswith(".avif") or
file.name.endswith(".AVIF"):
I tried putting all the file type strings into a list and using the any()
function but the problem is that any() gives a boolean output, while the file.name.endswith()
function requires a str input.
Any ideas on how to simplify this line?
Answers:
os.path.splitext()
can split the extension off a filename, and using lower()
can avoid the need to handle differently-cased variants separately:
valid_extensions = set(['.jpg', '.jpeg', '.heic', '.png', '.avif'])
def check_extension(filename):
return os.path.splitext(filename)[1].lower() in valid_extensions
This works as:
>>> check_extension('good.JPEG')
True
>>> check_extension('bad.zip')
False
Based on your use of file.name
, I’m guessing file
is probably a Path object. If so, in addition to the name
attribute, it also has a suffix
which contains the file extension (and stem
, which is the part of the filename before the extension and can come in handy for other things). Once you have the suffix, you can lower-case it and check for its membership in a set (which is more efficient than checking membership in, for example, a list).
if file.suffix.lower() in {'.jpg', '.jpeg', '.heic', '.png', '.avif'}:
str.endswith()
accepts a tuple of strings and any match is True
. Also use str.lower()
so you don’t need to check for upper and lower case separately.
if file.name.lower().endswith((".jpg", ".jpeg", ".heic", ".png", ".avif")):
I’m trying to write a program that essentially divides different file types among different directories. My computer does have many different image file types, so it makes a very long line in my code:
if file.name.endswith(".jpg") or
file.name.endswith(".JPG") or
file.name.endswith(".jpeg") or
file.name.endswith(".JPEG") or
file.name.endswith(".heic") or
file.name.endswith(".HEIC") or
file.name.endswith(".png") or
file.name.endswith(".PNG") or
file.name.endswith(".avif") or
file.name.endswith(".AVIF"):
I tried putting all the file type strings into a list and using the any()
function but the problem is that any() gives a boolean output, while the file.name.endswith()
function requires a str input.
Any ideas on how to simplify this line?
os.path.splitext()
can split the extension off a filename, and using lower()
can avoid the need to handle differently-cased variants separately:
valid_extensions = set(['.jpg', '.jpeg', '.heic', '.png', '.avif'])
def check_extension(filename):
return os.path.splitext(filename)[1].lower() in valid_extensions
This works as:
>>> check_extension('good.JPEG')
True
>>> check_extension('bad.zip')
False
Based on your use of file.name
, I’m guessing file
is probably a Path object. If so, in addition to the name
attribute, it also has a suffix
which contains the file extension (and stem
, which is the part of the filename before the extension and can come in handy for other things). Once you have the suffix, you can lower-case it and check for its membership in a set (which is more efficient than checking membership in, for example, a list).
if file.suffix.lower() in {'.jpg', '.jpeg', '.heic', '.png', '.avif'}:
str.endswith()
accepts a tuple of strings and any match is True
. Also use str.lower()
so you don’t need to check for upper and lower case separately.
if file.name.lower().endswith((".jpg", ".jpeg", ".heic", ".png", ".avif")):