【问题标题】:Batch filename rename with conditional or math operation使用条件或数学运算批量重命名文件名
【发布时间】:2016-11-21 12:16:24
【问题描述】:

这是我的第一个问题。提前致谢。

我已经自动将数百张图片上传到 Webfaction 服务器,但文件名中的时间戳不正确,现在我必须重命名它们。

这是一个例子:

  • tl0036_20161121-120558.jpg

  • myCode_yyyymmdd_hhmmss.jpg

我必须在 1 小时前更改“hh”字符,所以 12 应该是 11。它们是第 17 位和第 18 位。我想有两种方法:

  • 数学运算:图像是从凌晨 1 点到晚上 11 点拍摄的,因此我认为只对所有图像进行 12-1=11 之类的数学运算没有问题。
  • 条件:如果第17和第18个字符的值为12,则重命名为11。应写入24个条件,从01到23起始值。

我在这里找到了很多关于替换/重命名固定字符串和其他关于条件操作的答案,但没有关于我的混合替换。

我需要关于脚本应该如何的建议,假设它将被执行到文件夹中。我是一个使用 bash 或 python 的新手。

谢谢!

【问题讨论】:

    标签: python bash conditional batch-rename webfaction


    【解决方案1】:

    在 Python 中使用 datetime 的解决方案

    import time
    import datetime
    
    def change_filename(fn):
    
        # EXTRACT JUST THE TIMESTAMP AS A STRING
        timestamp_str = fn[7:22]
    
        # CONVERT TO UNIX TIMESTAMP
        timestamp = time.mktime(datetime.datetime.strptime(timestamp_str, "%Y%m%d-%H%M%S").timetuple())
    
        # SUBTRACT AN HOUR (3600 SECONDS)
        timestamp = timestamp - 3600
    
        # CHANGE BACK TO A STRING
        timestamp_str = datetime.datetime.fromtimestamp(timestamp).strftime("%Y%m%d-%H%M%S")
    
        # RETURN THE FILENAME WITH THE NEW TIMESTAMP
        return fn[:7] + timestamp_str + fn[22:]
    

    这考虑了通过将时间戳倒退一小时而可能发生的日、月和年的变化。如果您使用的是 12 小时制而不是 24 小时制,则可以改用格式字符串 "%Y%m%d-%I%M%S";见Python docs

    归功于:Convert string date to timestamp in PythonConverting unix timestamp string to readable date in Python

    这假定您的 myCode 是固定长度的,如果不是,您可以使用 str.split 方法从 - 之后提取小时数,或者如果您的文件名有未知的数字/位置 @ 987654336@s,您可以查看使用regular expressions 来查找时间,并使用capturing groups 查找时间和replace

    在 Python 中,您可以结合使用 globshutil.move 来遍历文件并使用该函数重命名它们。如果目录/ies 中还有其他文件,您可能希望使用正则表达式来确保仅对匹配命名方案的文件进行操作。

    简单的解决方案

    上面有关于myCode 长度和文件名格式的注意事项。

    如果您的时间戳使用 24 小时格式(00-23 小时),那么您可以通过减一来替换小时,如您所说;但是您必须使用条件来确保将23 转换为00,并注意将前导零添加到小于10 的小时数。

    Python 中的一个例子是:

    def change_filename(fn):
    
        hh = int(fn[16:18])
    
        if hh == 0:
            hh = 23
        else:
            hh -= 1
    
        hh = str(hh)
    
        # ADD LEADING ZERO IF hh < 10
        if len(hh) == 1:
            hh = '0' + hh
    
        return fn[:16] + str(hh) + fn[18:]
    

    如上所述,要记住的重要一点是,如果小时为 00 并更改为 23,此方法不会将日期倒退 1,因此您还必须考虑到这一点。月份和年份也可能发生同样的情况,您必须将这些都考虑在内。最好使用datetime

    【讨论】:

      【解决方案2】:

      对于您的文件重命名逻辑,您不仅会遇到日边界问题,还会遇到月、年和闰年边界问题。例如,如果您的文件名是tl0036_20160101-000558.jpg,则需要更改为tl0036_20151231-230558.jpg。另一个例子:tl0036_20160301-000558.jpg 将是tl0036_20160229-230558.jpg

      从头开始创建此逻辑将非常耗时 - 但幸运的是 Python 中的 datetime 模块已经内置了所有这些逻辑。

      您的脚本应包含以下步骤:

      1. 遍历文件夹中的每个 '.jpg' 文件。
      2. 尝试为每个'.jpg' 匹配您的时间戳文件名
      3. 提取时间戳值并从这些值中创建一个datetime.datetime 对象。
      4. datetime.datetime 对象中减去等于 1 小时的 datetime.timedelta 对象,并将其设置为新的时间戳。
      5. 使用您的新时间戳构造一个新文件名。
      6. 用新文件名替换旧文件名。

      这是一个示例实现:

      import datetime
      import glob
      import os
      import re
      
      def change_timestamps(source_folder, hourdiff = -1):
      
          file_re = re.compile(r'(.*)_(\d{8}-\d{6})\.jpg')
          for source_file_name in glob.iglob(os.path.join(source_folder, '*.jpg')):
              file_match = file_re.match(source_file_name)
              if file_match is not None:
                  old_time = datetime.datetime.strptime(file_match.group(2), "%Y%m%d-%H%M%S")
                  new_time = old_time + datetime.timedelta(hours = hourdiff)
                  new_file_str = '{}_{}.jpg'.format(file_match.group(1), new_time.strftime("%Y%m%d-%H%M%S"))
                  new_file_name = os.path.join(source_folder, new_file_str)
                  os.replace(source_file_name, new_file_name)
      

      【讨论】:

        猜你喜欢
        • 2018-05-26
        • 1970-01-01
        • 2017-04-20
        • 2013-12-19
        • 2013-07-26
        • 2010-10-10
        • 2011-01-23
        • 1970-01-01
        相关资源
        最近更新 更多