You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux下按文件名ddmmyyyy日期批量归类图片至yyyy/mm/dd目录

需求与问题描述

我有大量格式如下的图片文件:

randomname_08042020_1837_sometext_somemoretext.jpg
randomname_17012022_1650_sometext_somemoretext.th.jpg
randomname_08042020_1837_sometext_somemoretext.th.jpg
randomname_17012022_1658_sometext_somemoretext.jpg
randomname_09042020_0009_sometext_somemoretext.jpg
randomname_17012022_1658_sometext_somemoretext.th.jpg
randomname_09042020_0009_sometext_somemoretext.th.jpg
randomname_17012022_1711_sometext_somemoretext.jpg
randomname_15062020_1736_sometext_somemoretext.jpg
randomname_17012022_1711_sometext_somemoretext.th.jpg
randomname_15062020_1736_sometext_somemoretext.th.jpg
randomname_17012022_1719_sometext_somemoretext.jpg
randomname_09052020_1812_sometext_somemoretext.jpg
randomname_17012022_1719_sometext_somemoretext.th.jpg
randomname_09052020_1812_sometext_somemoretext.th.jpg
randomname_17012022_1730_sometext_somemoretext.jpg
randomname_09052020_1838_sometext_somemoretext.jpg
randomname_17012022_1730_sometext_somemoretext.th.jpg
randomname_09052020_1838_sometext_somemoretext.th.jpg
randomname_17092021_2340_sometext_somemoretext.jpg

需要编写脚本,根据文件名中第一个下划线后的ddmmyyyy格式日期,将图片分类到yyyy/mm/dd结构的文件夹中(需自动创建文件夹)。

之前尝试修改基于sed的脚本但无效,修改后的脚本既不移动文件也不报错:

#!/bin/bash

cd /opt/large-out
for file in *.jpg; do
  date=$(printf "$file" | sed -nE 's/.*_([01][0-9])([0-9]{4})([0-3][0-9])([0-9]{4})_.*/\3\/\2\/\1/p')
  if [ -n "$date" ]; then
    mkdir -p "$date" && mv "$file" "$date"
  fi
done

问题分析

你修改后的sed正则表达式完全错误,没有匹配到文件名的结构:

  • 原文件名中第一个下划线后是ddmmyyyy(8位数字:日2位+月2位+年4位),比如08042020对应08日 04月 2020年
  • 你的正则里错误地捕获了4段数字,和实际的8位ddmmyyyy结构不符,导致匹配失败,date变量为空,脚本因此没有执行后续操作。

正确脚本方案

以下是适配你文件名格式的两种bash脚本实现:

方案1:sed正则匹配版

#!/bin/bash

cd /opt/large-out || exit 1  # 切换目录失败则直接退出

for file in *.jpg *.th.jpg; do  # 匹配两种后缀的图片文件
  # 捕获第一个下划线后的ddmmyyyy,分组为(dd)(mm)(yyyy),转换为yyyy/mm/dd格式
  dir_path=$(echo "$file" | sed -nE 's/^[^_]+_([0-9]{2})([0-9]{2})([0-9]{4})_.*/\3\/\2\/\1/p')
  
  if [ -n "$dir_path" ]; then
    mkdir -p "$dir_path" && mv "$file" "$dir_path"
  fi
done

方案2:纯bash字符串处理版(无需外部工具,效率更高)

#!/bin/bash

cd /opt/large-out || exit 1

for file in *.jpg *.th.jpg; do
  # 按下划线分割文件名,提取第一个下划线后的日期段
  date_segment=${file#*_}  # 移除第一个下划线及之前的内容
  date_segment=${date_segment%%_*}  # 移除第二个下划线及之后的内容
  
  # 验证是否为8位数字的日期段
  if [[ $date_segment =~ ^[0-9]{8}$ ]]; then
    dd=${date_segment:0:2}
    mm=${date_segment:2:2}
    yyyy=${date_segment:4:4}
    dir_path="${yyyy}/${mm}/${dd}"
    
    mkdir -p "$dir_path" && mv "$file" "$dir_path"
  fi
done

脚本说明

  • cd /opt/large-out || exit 1:确保切换目录失败时脚本直接退出,避免后续操作出现错误
  • *.jpg *.th.jpg:覆盖所有.jpg和.th.jpg后缀的图片文件
  • 方案1的sed正则:^[^_]+_匹配第一个下划线前的任意内容,精准捕获dd、mm、yyyy三段数字并转换为目标路径格式
  • 方案2使用bash内置的字符串截取功能,无需调用外部工具,处理大量文件时速度更快

内容的提问来源于stack exchange,提问作者asteroids_r_fun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 03:15:42