0

我需要用 EXIF 数据重命名我的图片,但是我有一个问题:如果我使用“:”来分隔时间(小时:分钟:秒),文件名会变得疯狂!

metadata = pyexiv2.ImageMetadata(lunga + i)
metadata.read()
tag = metadata['Exif.Image.DateTime']
estensione = ".jpg"
new_data = tag.value.strftime('%Y-%m-%d %H-%M-%S')
new_name = lunga + str(new_data) + estensione
os.renames(lunga + i, new_name)     

效果很好,但有

    new_data = tag.value.strftime('%Y-%m-%d %H:%M:%S')

我得到类似的东西

2A443K~H.jpg
4

2 回答 2

2

问题是您不允许在 Windows 上将冒号放入文件名中。您实际上并未使用 Windows……但您使用的是 SMB 共享,这意味着您受 Windows 规则的约束。

解决方法是不要将冒号放入文件名中。

如果您想了解为什么会发生这种奇怪的事情,请继续阅读。


Windows 文件名的详细信息在 MSDN 的命名文件、路径和命名空间中进行了描述,但我将在这里总结相关部分。

Windows 下的 NT 内核对冒号没有问题,但它上面的 Win32 层无法处理它们(MSVCRT 中的 quasi-POSIX 层位于 Win32 之上)。

因此,在 C 级别,如果您调用 NT 函数,例如NtSetInformationFile,它会很好地保存它们。如果你调用 Win32 函数如MoveFileEx,它们通常会给你一个错误,但如果你使用特殊\\?\语法说“将此名称直接传递给 NT”,它会起作用。如果你调用 MSVCRT 之类的函数rename,你会得到一个错误。旧版本的 Python 称为rename,它只会给你一个错误。较新的版本调用MoveFileEx,并将尝试将名称包装在\\?\语法中(因为这也允许您绕过其他一些愚蠢的限制,例如过短的MAX_PATH值)。

那么,如果你给一个文件取了一个 Win32 无法理解的名字会怎样呢?请记住,在 Windows 上,每个文件都有两个不同的名称:“长名称”和“短名称”。短名称是 DOS 风格的 8.3 文件名。因此,当它无法显示长名称时,它会显示短名称。

简称从何而来?如果您没有显式创建一个,Windows 将使用前 6 个字符、一个波浪号和一些字母从长名称中为您创建一个。因此,例如,的简称"Program Files""PROGRA~1"。但如果 Windows 不能处理长名称,它只会用 6 个随机字符、一个波浪号和一个随机字符组成一个短名称。所以你得到类似的东西2A443K~H

为 Windows 设计的 NTFS 文件系统期望以 Windows-y 方式使用。因此,如果您使用的是 NTFS 卷,即使在非 Windows 系统上,驱动程序也会模拟其中的一些功能,为您提供类似但不相同的行为。

当然,如果您正在与来自 Windows 系统的共享或由非 Windows 系统上的 NTFS 驱动器支持的共享通信,同样,一些相同的事情将适用。

即使您的计算机和文件服务器都是非 Windows 并且文件系统不是 NTFS,如果您使用 SMB/CIFS 进行文件共享,SMB 也是为 Windows 设计的,您将再次获得类似的行为。

至少您不再需要担心 VMS、经典 Mac 和其他命名系统,只需 POSIX 和 Windows。

于 2013-11-14T23:03:39.380 回答
1

冒号是 Windows 文件系统中的保留字符(请参阅如何使用无效字符创建文件名,例如 :?>?),因此该名称被替换为自动生成的 on 。

需要明确的是,这不是Python 问题。如果您不希望发生这种情况,请不要在文件名中使用冒号或其他保留字符。

于 2013-11-14T23:03:07.290 回答