【问题标题】:How to add an id to filename before extension?如何在扩展之前为文件名添加 id?
【发布时间】:2016-05-27 15:54:18
【问题描述】:

我有一个文件名:name.ext

我想做以下事情:

name + id + '.' + ext for name, ext in filename.split()

或者找到一种更好的方法来获取文件名并在扩展名之前的末尾添加一个随机的 7 个字符的字符串。

这是我目前所拥有的:

def generate_id(size=7, chars=string.ascii_uppercase + string.digits):
    return ''.join(random.choice(chars) for _ in range(size))

def append_id(filename):
    return (name + '_' + generate_id() + '.' + ext for name, ext in filename.split('.'))

但它把它当作一个生成器表达式,这不是我想要的结果。

编写append_id 函数的正确方法是什么?

【问题讨论】:

  • for name, ext in filename.split('.') 不会在nameext 中为您提供集合的两个连续元素,但会尝试将每个集合的元素解压缩为两个变量:nameext .
  • 是的,现在我看到了问题所在。正在尝试做一个列表组合

标签: python


【解决方案1】:

要在一行中完成,您可以尝试:

def append_id(filename):
    return "{0}_{2}.{1}".format(*filename.rsplit('.', 1) + [generate_id()])

不过,它的可读性不是很好。

大多数语言实现都提供了处理文件名的函数,Python 也不例外。你应该使用os.path.splitext:

def append_id(filename):
  return "{0}_{2}{1}".format(*os.path.splitext(filename) + (generate_id(),))

请注意,第二个版本需要两个额外的修改:

  • splitext 返回一个元组而不是一个列表,所以我们需要用一个元组包装generate_id 的结果
  • splitext 保留点,所以你需要从格式字符串中删除它

不过,我不会在此处使用 oneliner - 请参阅下一个答案以获得更易读的解决方案。

Python 3.4 引入了pathlib 模块,你可以这样使用它:

from pathlib import Path

def append_id(filename):
  p = Path(filename)
  return "{0}_{2}{1}".format(p.stem, p.suffix, generate_id())

这仅适用于没有前面路径的文件名。对于带有路径的文件,请使用:

from pathlib import Path

def append_id(filename):
  p = Path(filename)
  return "{0}_{2}{1}".format(Path.joinpath(p.parent, p.stem), p.suffix, generate_id())

在 Python 3.9 中还有 with_stem,这可能是这种情况下最合适的选择。

【讨论】:

    【解决方案2】:

    我建议一些简单明了的方法 - 使用 os.path.splitext 检索基本名称和扩展名,然后通过 str.format 方法简单地合并所有结果组件。

    import os
    import random
    import string
    
    def generate_id(size=7, chars=string.ascii_uppercase + string.digits):
        return ''.join(random.choice(chars) for _ in range(size))
    
    def append_id(filename):
        name, ext = os.path.splitext(filename)
        return "{name}_{uid}{ext}".format(name=name, uid=generate_id(), ext=ext)
    

    一些测试用例:

    append_id("hello.txt")
    append_id("hello")
    append_id("multiple.dots.in.file")
    

    【讨论】:

    • 如果filename 是类似C:/path/filename.txt 的路径,这是否可行
    【解决方案3】:

    从 Python 3.4 开始,处理路径的好工具是 pathlib。这会将路径视为 对象 而不是 字符串,并提供强大的界面。

    从 Python 3.9 开始,添加了一个新方法 - with_stem,所以你的函数可以是:

    from pathlib import Path
    
    def append_id(filename):
        path = Path(filename)
        return path.with_stem(f"{path.stem}_{generate_id()}")
    

    对于旧版本,您仍然可以使用with_name 方法:

    from pathlib import Path
    
    def append_id(filename):
        path = Path(filename)
        return path.with_name(f"{path.stem}_{generate_id()}{path.suffix}")
    

    这些函数是通用的,也适用于完整/相对路径,而不仅仅是文件名:

    >>> append_id("sample.text")
    PosixPath('sample_PBMQBFD.text')
    
    >>> append_id("/a/b/c/sample.text")
    PosixPath('/a/b/c/sample_UMTYXCP.text')
    

    请注意,将返回特定于平台的 Path 对象。您总是可以使用str() 将其转换回字符串:

    >>> str(append_id("/a/b/c/sample.text"))
    '/a/b/c/sample_O1LPTEC.text'
    

    【讨论】:

    • 我不能没有 pathlib。感谢您发布此信息!
    • 截至 2021 年 6 月,这对我来说是最新且最简单的答案。
    【解决方案4】:
    def append_id(filename):
        parts = filename.split('.')
        return "".join(parts[:-1])+ '_' + generate_id() + '.' + parts[-1]
    

    【讨论】:

      【解决方案5】:

      你的随机生成的单行答案 -

      map(lambda x :x.split(".")[0] + "_" + hashlib.md5(("%.15f" % time.time())+"_"+''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(5))).hexdigest()[:7]+"."+x.split(".")[1], filenames)

      这里可以输入filenames作为列表

      刚刚使用了一个随机 id 生成函数,它需要时间和 5 个字符 md5 的随机字符串,并从中获取前 7 个字符。

      它的可读性不是很好,但是由于您要求使用单行解决方案,所以我想不出更详细的方法。

      【讨论】:

        【解决方案6】:

        要修复您的 generate_id 代码,您需要一个列表理解。

        def generate_id(size=7, chars=string.ascii_uppercase + string.digits):
            return '_' + ''.join([random.choice(chars) for _ in range(size)])
        

        你使用 python 只是为了重命名文件吗?您可以改用pwgen 之类的命令行程序。

        mv $filename ${filename/%.ext/_$(pwgen 6 1).ext}
        

        如果您从 Python 写入文件,请考虑使用 tempfile.NamedTemporaryFile 和适当的选项。 (delete=False, dir=".", prefix="...", suffix="...")

        【讨论】:

        • 只是在移动时给同名文件添加一个字符串
        猜你喜欢
        • 1970-01-01
        • 2014-06-12
        • 1970-01-01
        • 2013-11-03
        • 1970-01-01
        • 2021-12-26
        • 1970-01-01
        • 1970-01-01
        • 2015-09-08
        相关资源
        最近更新 更多