当我需要将 EXIF DateTaken 作为日期和时间或 Int 时,将其提取为 Str

问题描述 投票:0回答:3

尝试重命名家庭照片,我希望此文件夹中的所有照片都重命名为

mmdd__00X

所以 3 月 23 日的第 20 张图像的文件名应该是

0323__020

我的很多代码都来自其他线程,我使用了来自 Python 文件创建日期和重命名 - 请求批评 对于大部分内容,但发现我需要拍摄日期(exif 数据)而不是创建日期。问题是,Pillow 中的 EXIF 模块将拍摄日期标记作为字符串,但我需要它是 int 或 datetime 以便我能够修改。或者我可以解析字符串以适合我的命名格式吗?

import os
import datetime
from PIL import Image

target = input('Enter full directory path: ')
os.chdir(target)
allfiles = os.listdir(target)
counter = 0

def get_date_taken(path):
    return Image.open(path)._getexif()[36867]

for filename in allfiles:
        t = get_date_taken(filename)
        v = datetime.datetime.fromtimestamp(t)
        x = v.strftime('%m%d')
        y = '{:02d}'.format(counter)
        try:
            os.rename(filename, x+"__"+y+".jpg")
        except FileExistsError:
            while True:
                try:
                    counter += 1
                    y = '{:02d}'.format(counter)
                    os.rename(filename, x+"__"+y+".jpg")
                except FileExistsError:
                    continue
                counter = 0
                break

第一个真正的程序,任何帮助将不胜感激。

python string exif python-imaging-library
3个回答
2
投票

首先将日期时间字符串解析为时间结构,然后可以根据需要进行格式化:

from PIL import Image
DateTimeOriginal = 36867

for filename in os.listdir('.'):

    if isfile(filename) and filename.endswith('.jpg'):
        try:
            dto_str = Image.open(filename)._getexif()[DateTimeOriginal]
            dto = time.strptime(dto_str, '%Y:%m:%d %H:%M:%S')
        except (KeyError, TypeError):
            print('error: no exif datetime value found for %r.' % filename)
            continue

        print(filename, dto)
        new_filename = time.strftime('…', dto)
        # os.rename(filename, new_filename)

更新: 现在 DateTime 支持 fromisoformat(),您还可以使用以下方法解析字符串:

dto = DateTime.fromisoformat(dto_str.replace(':', '-', 2))

0
投票

或者我可以解析字符串以适合我的命名格式吗?

是的。使用

strptime()
然后
strftime
就像您对所需格式所做的那样(ps,您可以将下划线移动到 strftime 调用)


0
投票

好吧,如果您使用的是 Windows,那么您的 try 块中将出现一个

OSError
,并且您的代码将使用以下增强功能(又名 idk 足够了解
.format
的事情)。请参阅下面的
os.listdir
建议。

for filename in allfiles:
    t = get_date_taken(filename)
    v = datetime.strptime(t, 'enter format of t here')
    x = v.strftime('%m%d__%H%M%S')+str(counter).zfill(3)+'.jpg'
    try:
        os.rename(filename, x)
    except OSError:
        # etc...

此代码也无法在 MacOS 和 Linux 上运行!您将删除很多文件!

os.rename()
如果目标文件与源文件同名,则覆盖目标文件

修复建议如下,但首先

os.listdir
列出了包括子目录在内的所有内容。如果您想要所有文件,请这样做

allfiles = [f for f in os.listdir(target) if os.path.isfile(os.path.join(target, f)]
#...or if you want only jpgs...
allfiles = [f for f in os.listdir(target) if os.path.isfile(os.path.join(target, f) and (f.lower().endswith('.jpg') or f.lower().endswith('.jpeg))]

好的,建议:我建议重命名所有附加整个日期时间的文件(如果您每秒拍摄多张图像,则可以添加微秒)。例如

for filename in allfiles:
    t = get_date_taken(filename)
    v = datetime.strptime(t, 'enter format of t here')
    x = v.strftime('%m%d__%H%M%S')+'.jpg'
    os.rename(filename, x)
    filename = x

因此,如果一切顺利,

allfiles
是所有重命名文件的列表。排序应该按天为您提供升序或降序的图片,检查哪个并确保列表从最早到最新。

然后使用计数器进行迭代,该计数器在给定日期为每张照片递增,到达新的一天时重置为 0,并用计数器替换文件名的时间部分。时间部分的长度是固定的,你的扩展也是固定的,这样你就可以砍掉最后的部分。

就是这样。由于它会两次遍历您的文件并进行排序,因此需要更长的时间,但我想谨慎行事。这样做的好处是它会按时间组织您的文件。


对上述代码块的改进是,如果在重命名过程中引发异常,则将重命名的文件转换回原始文件名,以便您无需编写新代码即可再次运行代码。这需要保留一个新文件名列表,如下所示:

new_names = []
for filename in allfiles:
    v = datetime.strptime(t, 'enter format of t here')
    x = v.strftime('%m%d__%H%M%S')+'.jpg'
    try:
        os.rename(filename, x)
    except:
        print 'something went wrong, reverting changes...'
        for new, old in zip(new_names, allfiles[:len(new_names)]):
            os.rename(new, old)
        raise
    else:
        filename = x
        new_names.append(x)
© www.soinside.com 2019 - 2024. All rights reserved.