关于python:从任何(不安全)字符串创建(sane/safe)文件名

Create (sane/safe) filename from any (unsafe) string

我想从一些随机的Unicode字符串(MICH可能只包含任何内容)创建一个健全/安全的文件名(即,有些可读性,没有"奇怪"字符等)。

(对于我来说,函数是否是cocoa、objc、python等并不重要。)

当然,可能有无限多的字符,这可能很奇怪。因此,拥有黑名单并随着时间的推移向黑名单中添加越来越多的黑名单并不是真正的解决方案。

我可以有一个白名单。但是,我真的不知道如何定义它。[a-zA-Z0-9 .]是一个开始,但我也希望接受可以以正常方式显示的Unicode字符。


Python的:

1
"".join([c for c in filename if c.isalpha() or c.isdigit() or c==' ']).rstrip()

本removes线断,但接受Unicode字符,等等。

例子:

1
2
filename = u"ad
bla'{-+\)(??"

adbla?给:

编辑str.isalnum()是alphanumeric在一步。–从queueoverflow下面的评论。danodonovan hinted on a点包括保鲜。

1
2
    keepcharacters = (' ','.','_')
   "".join(c for c in filename if c.isalnum() or c in keepcharacters).rstrip()


我的需求是保守的(文件名是有效的生成需要在多操作系统,包括一些古代移动OSS)。i端的:

1
   "".join([c for c in text if re.match(r'\w', c)])

这是怀特列出alphanumeric字符(a-z,A-Z,0-9和下划线)。正则表达式,可以在编译和缓存的效率,如果有很多的一个匹配的字符串。我有一个案例,它不会制造任何重大差。


有一个合理的答案在这里,但我想要一些用例,这可能是一个标点符号和字符串中删除而不只是这些,我想我有下划线替换它。即使是一个允许在文件名中的字符是最problematic os的他们。所以,在我的案例,如果包含原始字符串a的周期,我不希望通过进入或通过文件名,它会产生额外的扩展",我可能不想(我自己发生的延伸)

1
2
3
4
5
6
7
8
9
def make_safe_filename(s):
    def safe_char(c):
        if c.isalnum():
            return c
        else:
            return"_"
    return"".join(safe_char(c) for c in s).rstrip("_")

print(make_safe_filename("hello you crazy $#^#& 2579 people!!! : die!!!" ) +".gif")

照片:

hello_you_crazy_______2579_people______die___.gif


什么是更多或更少的水在一起。但在反向(regexp replace,任何需要的列):

1
2
3
4
5
>>> import re
>>> filename = u"ad
bla'{-+\)(?1?"

>>> re.sub(r'[^\w\d-]','_',filename)
u'ad_bla__-_____1_'

这里唯一的问题没有解决方案,你必须考虑:

  • 什么是您的最大的最小长度的文件名?(例如DOS只支持8 11个字符;操作系统不支持大于256个字符)

  • 禁止在一些上下文的文件名是什么?安静(Windows不支持保存为文件CON.TXT-湖blogs.msdn.microsoft.com http://///oldnewthing 20031022 00?P = 42073)

  • 记住,这是有意义的和特异性...(电流/父目录),因此是不安全的。

  • 有一个文件名要发生碰撞的风险-要么由于排出(或是使用相同的文件名字符多元时代?

考虑只使用散列数据和hexdump of,as a文件名?


Python的:

1
2
for c in r'[]/\;,><&*:%=+@!#^()|?^':
    filename = filename.replace(c,'')

(例子),你要只是想删除人物)在前面的r字符串的字符串是可以理解的,在它的原始格式,允许你删除反斜杠\为好

编辑:解决方案:在Python正则表达式

1
2
import re
re.sub(r'[]/\;,><&*:%=+@!#^()|?^', '', filename)