检查文件名是否有效

5 投票
3 回答
16180 浏览
提问于 2025-04-17 22:12

在Python中,怎样才能最稳妥地检查一个文件名在所有平台上(包括手机平台,比如Android和iOS)是否有效呢?

举个例子:

this_is_valid_name.jpg -> 有效

**adad.jpg -> 无效

a/ad -> 无效

3 个回答

-2

相关主题是:“文件名模式匹配”。

这里有一些你可以使用的方法和函数:

  1. 字符串方法 endswith() 和 startswith()

  2. fnmatch.fnmatch()

  3. glob.glob()

  4. pathlib.Path.glob()

import os
# Get .txt files
for f_name in os.listdir('some_directory'):
    if f_name.endswith('.txt'):
       print(f_name)

使用 fnmatch() 进行简单的文件名模式匹配

import os
import fnmatch
for file_name in os.listdir('some_directory/'):
    if fnmatch.fnmatch(file_name, '*.txt'):
       print(file_name)

更高级的模式匹配

for filename in os.listdir('.'):
    if fnmatch.fnmatch(filename, 'data_*_backup.txt'):
       print(filename)

使用 glob 进行文件名模式匹配

import glob
glob.glob('*.py')

或者代码如下

import glob
for name in glob.glob('*[0-9]*.txt'):
    print(name)

或者匹配如下

import glob
for file in glob.iglob('**/*.py', recursive=True):
    print(file)

或者代码如下

from pathlib import Path
p = Path('.')
for name in p.glob('*.p*'):
    print(name)
1

我自己写了一个函数。我是以@Voo的回答为基础,然后根据这个回答添加了一些检查。

import re

def is_valid_folder_name(name: str):
    # Define a regular expression pattern to match forbidden characters
    ILLEGAL_NTFS_CHARS = r'[<>:/\\|?*\"]|[\0-\31]'
    # Define a list of forbidden names
    FORBIDDEN_NAMES = ['CON', 'PRN', 'AUX', 'NUL',
                       'COM1', 'COM2', 'COM3', 'COM4', 'COM5',
                       'COM6', 'COM7', 'COM8', 'COM9',
                       'LPT1', 'LPT2', 'LPT3', 'LPT4', 'LPT5',
                       'LPT6', 'LPT7', 'LPT8', 'LPT9']
    # Check for forbidden characters
    match = re.search(ILLEGAL_NTFS_CHARS, name)
    if match:
        raise ValueError(
            f"Invalid character '{match[0]}' for filename {name}")
    # Check for forbidden names
    if name.upper() in FORBIDDEN_NAMES:
        raise ValueError(f"{name} is a reserved folder name in windows")
    # Check for empty name (disallowed in Windows)
    if name.strip() == "":
        raise ValueError("Empty file name not allowed in Windows")
    # Check for names starting or ending with dot or space
    match = re.match(r'^[. ]|.*[. ]$', name)
    if match:
        raise ValueError(
            f"Invalid start or end character ('{match[0]}')"
            f" in folder name {name}"
        )

在你的例子中:

$ is_valid_folder_name('this_is_valid_name.jpg')
$ is_valid_folder_name('**adad.jpg')
---------------------------------------------------------------------------
ValueError in is_valid_folder_name(name)
     13     match = re.search(ILLEGAL_NTFS_CHARS, name)
     14     if match:
---> 15         raise ValueError(
     16             f"Invalid character {match[0]} for filename {name}")
     17     # Check for forbidden names

ValueError: Invalid character '*' for filename **adad.jpg
$ is_valid_folder_name('a/ad')
---------------------------------------------------------------------------
ValueError in is_valid_folder_name(name)
     13     match = re.search(ILLEGAL_NTFS_CHARS, name)
     14     if match:
---> 15         raise ValueError(
     16             f"Invalid character {match[0]} for filename {name}")
     17     # Check for forbidden names

ValueError: Invalid character '/' for filename a/ad

如果有人发现我漏掉了什么,请随意补充或评论!

4

检查一个文件名在你目标操作系统上是否有效,最直接的方法就是把它和一份经过测试的文件名列表对比。

valid = myfilename in ['this_is_valid_name.jpg']

进一步说,你可以定义一套允许的字符,这些字符在所有平台上都是可以用作文件名的:

valid = set(valid_char_sequence).issuperset(myfilename)

不过,这样还不够,因为有些操作系统有保留的文件名

你需要排除这些保留的名字,或者创建一个表达式(正则表达式),用来匹配操作系统允许的文件名范围,并且在每个目标平台上测试你的文件名。

据我所知,Python并没有提供这样的帮助工具,因为它遵循一个原则:宁可事后求原谅,也不要事先请求许可。因为不同的操作系统和文件系统组合很多,等操作系统抛出异常时再做出反应,往往比提前检查所有可能的安全文件名范围要简单。

撰写回答