【问题标题】:How do I append parts of the directory names in a file's path to the file's name in bash or python?如何将文件路径中的部分目录名称附加到 bash 或 python 中的文件名称?
【发布时间】:2019-04-21 09:23:12
【问题描述】:

我最近从我的 MacOS 系统中解放出来。我最担心的一个问题是保存我在 iPhoto 中保存了 14 年的家庭照片。

我决定导出所有 17000 多张图像,并将它们放入按年、月和日组织的文件夹树中。问题是文件本身不包含有关何时拍摄图像的信息。识别图像拍摄时间的唯一属性是它们所在的文件夹。

现在,我的“图片”文件夹树如下所示:

 2004/    
 2005/    
 2006/    
 2007/    
 2008/    
 2009/    
 2010/    
 2011/    
 2012/    
      01_January/    
      02_February/    
      03_March/    
      04_April/    
      05_May/    
      06_June/       
           18June, 2012/    
                File - 001.jpg     
                File - 002.jpg    
                File - 003.jpg    
                etc...    
           24June, 2012/    
                File - 001.jpg    
                File - 002.jpg    
                File - 003.jpg    
                etc...    
      07_July/    
      08_August/    
      09_September/    
      10_October/    
      11_November/    
      12_December/
 2013/    
 2014/    
 2015/    
 2016/    
 2017/    
 2018/   

每年目录包含十二个月的目录。每个月目录仅在有当天的图像时才包含一个日目录。

我想要做的是附加所有图像文件名,以便它们包含上级目录中的元素:

例子:

 ./2012/06_June/18June, 2012/      
      File - 001.jpg   ------->   2012-06-18_File - 001.jpg    
      File - 002.jpg   ------->   2012-06-18_File - 002.jpg    
      File - 003.jpg   ------->   2012-06-18_File - 003.jpg     
      etc...

有人可以帮我找到一种方法吗? Python 或 Bash 脚本,我可以在其中学习如何做到这一点。 谢谢。

【问题讨论】:

    标签: python bash directory rename filenames


    【解决方案1】:

    假设您在您的图片文件夹中,您可以尝试以下代码。请先检查新名称是否正确,然后取消注释行。

    from glob import glob
    import os
    import re
    for i in os.scandir(os.getcwd()):
        if i.is_dir():
            year = i.name
            os.chdir(i.name)
            for j in os.scandir(os.getcwd()):
               if j.is_dir() and os.listdir(j.name):
                   month = re.compile(r'(\d+)').split(j.name)[-2]
                   os.chdir(j.name)
                   for k in os.scandir(os.getcwd()):
                       if k.is_dir():
                           day = re.compile(r'(\d+)').split(k.name)[-4]
                           os.chdir(k.name)
                           for l in glob('*.jpg'):
                               newName = year + '-' + month + '-' + day + '_' + l
                               print(l)
                               print(newName)
                               # os.rename(l, newName)
                           os.chdir('..')
                   os.chdir('..')
            os.chdir('..')
    

    【讨论】:

    【解决方案2】:

    这是一个 (Shellcheck-clean) Bash 解决方案:

    #! /bin/bash
    
    shopt -s nullglob   # Globs that match nothing expand to nothing
    
    for file_path in [12][0-9][0-9][0-9]/[01][0-9]_*/[0-3][0-9]*/*.jpg ; do
        IFS=/ read -r year month_name day_month_year file_name <<<"$file_path"
        month=${month_name%%[^0-9]*}
        day=${day_month_year%%[^0-9]*}
    
        day_month_year_path=${file_path%/*}
        new_file_name=${year}-${month}-${day}_${file_name}
        new_file_path=${day_month_year_path}/${new_file_name}
    
        printf '    %s   ------->   %s\n' \
            "$file_path" "$new_file_path" >&2
    
        #UNCOMMENT mv -- "$file_path" "$new_file_path"
    done
    

    在包含年份目录(2004,...)的目录中运行它。

    如果您对它可以正确重命名文件感到满意,请从mv 行的开头删除#UNCOMMENT,然后再次运行它以实际重命名文件。

    有关IFS=/ read -r ... &lt;&lt;&lt;"$file_path" 行的工作原理的详细信息,请参阅How do I split a string on a delimiter in Bash?

    有关${var##pattern}${var%%pattern} 的信息,请参阅Removing part of a string (BashFAQ/100 (How do I do string manipulation in bash?))

    请参阅glob - Greg's Wiki 了解有关模式的信息,例如for 行、*/[^0-9]* 上的模式。

    【讨论】:

      【解决方案3】:

      我的解决方案是使用 python,只需在您的 PATH 中查找所有文件并使用字符串的总和来创建您的图像名称

      【讨论】:

      • 恐怕你的回答对OP没有太大帮助。
      猜你喜欢
      • 2020-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多