我有一个字符串,我想用它作为文件名,所以我想用Python删除文件名中不允许的所有字符。
我宁愿严格一点,所以假设我想只保留字母、数字和一小组其他字符,如“_-.()”。”。最优雅的解决方案是什么?
文件名需要在多个操作系统(Windows, Linux和Mac OS)上有效——它是我库中的一个MP3文件,以歌曲标题为文件名,并在3台机器之间共享和备份。
我有一个字符串,我想用它作为文件名,所以我想用Python删除文件名中不允许的所有字符。
我宁愿严格一点,所以假设我想只保留字母、数字和一小组其他字符,如“_-.()”。”。最优雅的解决方案是什么?
文件名需要在多个操作系统(Windows, Linux和Mac OS)上有效——它是我库中的一个MP3文件,以歌曲标题为文件名,并在3台机器之间共享和备份。
当前回答
Github上有个不错的项目叫python-slugify:
安装:
pip install python-slugify
然后使用:
>>> from slugify import slugify
>>> txt = "This\ is/ a%#$ test ---"
>>> slugify(txt)
'this-is-a-test'
其他回答
请记住,在Unix系统上实际上没有文件名限制
它可能不包含\0 它可能不包含/
其他一切都是公平的。
$ touch " > even multiline > haha > ^[[31m red ^[[0m > evil" $ ls -la -rw-r--r-- 0 Nov 17 23:39 ?even multiline?haha??[31m red ?[0m?evil $ ls -lab -rw-r--r-- 0 Nov 17 23:39 \neven\ multiline\nhaha\n\033[31m\ red\ \033[0m\nevil $ perl -e 'for my $i ( glob(q{./*even*}) ){ print $i; } ' ./ even multiline haha red evil
是的,我只是将ANSI颜色代码存储在一个文件名中,并使它们生效。
为了娱乐,在目录名中放入一个BEL字符,并观看当您CD到其中时所产生的乐趣;)
使用字符串作为文件名的原因是什么?如果人类的可读性不是一个因素,我会使用base64模块,它可以产生文件系统安全字符串。它是不可读的,但你不需要处理碰撞,而且它是可逆的。
import base64
file_name_string = base64.urlsafe_b64encode(your_string)
更新:根据Matthew的评论修改。
当遇到同样的问题时,我使用python-slugify。
Shoham也建议使用这种方法,但正如therealmarv指出的那样,默认情况下python-slugify也会转换圆点。
可以通过在regex_pattern参数中包含点来否决这种行为。
> filename = "This is a väryì' Strange File-Nömé.jpeg"
> pattern = re.compile(r'[^-a-zA-Z0-9.]+')
> slugify(filename,regex_pattern=pattern)
'this-is-a-varyi-strange-file-nome.jpeg'
方法复制的正则表达式模式
ALLOWED_CHARS_PATTERN_WITH_UPPERCASE
python-slugify包的slugify.py文件中的全局变量,并扩展为“。”
请记住,像.()这样的特殊字符必须用\转义。
如果您想保留大写字母,请使用小写=False参数。
> filename = "This is a väryì' Strange File-Nömé.jpeg"
> pattern = re.compile(r'[^-a-zA-Z0-9.]+')
> slugify(filename,regex_pattern=pattern, lowercase=False)
'This-is-a-varyi-Strange-File-Nome.jpeg'
这是使用Python 3.8.4和Python -slugify 4.0.1实现的
Github上有个不错的项目叫python-slugify:
安装:
pip install python-slugify
然后使用:
>>> from slugify import slugify
>>> txt = "This\ is/ a%#$ test ---"
>>> slugify(txt)
'this-is-a-test'
大多数解决方案都不起作用。
“你好/世界”——>“你好世界”
“/helloworld”/ ->“helloworld”
这通常不是你想要的,比如说你要为每个链接保存html,你要为不同的网页覆盖html。
我腌字典,如:
{'helloworld':
(
{'/hello/world': 'helloworld', '/helloworld/': 'helloworld1'},
2)
}
2表示应该追加到下一个文件名的数字。
我每次都从字典中查找文件名。如果它不在那里,我创建一个新的,如果需要追加最大的数字。