bash - 从文件名中提取日期子字符串

标签 bash

我正在尝试从 bash 中的字符串/文件路径中提取日期。这是我希望能实现但没有实现的功能:

#!/bin/bash

f=/mnt/media/CameraUploads/CMGPH_20190626_200707386.gif

if [[ $f =~ (19|20)\d\d(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01]) ]]; then
    strresult=${BASH_REMATCH[1]}
    echo $strresult
else
    echo "unable to parse string $f"
fi

我期待 $strresult = 20190626

我做错了什么?

最佳答案

最简单的方法就是使用带有子字符串删除的参数扩展来隔离日期,然后传递给date -d以转换为您想要的任何格式的日期比如说,

f=/mnt/media/CameraUploads/CMGPH_20190626_200707386.gif
t="${f%_*}"     ## trim from right to 1st '_'
t="${t##*_}"    ## trim from left to final '_' isolating date
date -d "$t"    ## call date format as needed

示例使用/输出

$ f=/mnt/media/CameraUploads/CMGPH_20190626_200707386.gif
> t="${f%_*}"     ## trim from right to 1st '_'
> t="${t##*_}"    ## trim from left to final '_' isolating date
> date -d "$t"    ## call date format as needed
Wed Jun 26 00:00:00 CDT 2019

如果您希望包含文件名的时间部分,您可以执行相同的操作。

要隔离完整的日期/时间字符串,您可以执行以下操作:

f=/mnt/media/CameraUploads/CMGPH_20190626_200707386.gif
t="${f%.*}"     ## trim from right to 1st '.'
t="${t##*_}"    ## trim from left to final '_' isolating time
t="${t:0:2}:${t:2:2}:${t:4:2}.${t:6:3}"     ## format time with : between 
d="${f%_*}"     ## trim from right to 1st '_'
d="${d##*_}"    ## trim from left to final '_' isolating date
d="${d:0:4}-${d:4:2}-${d:6:2}"              ## format date with - between
date -d "$d $t" ## call date format as needed

传递给date的最终“$d $t”字符串是:

2019-06-26 20:07:07.386

示例输出

Wed Jun 26 20:07:07 CDT 2019

编辑 - 文件名中任意位置的日期/时间

如果根据您的编辑,date_time 可以出现在文件名中的任何位置,并且 time 可能包含也可能不包含毫秒,则处理日期的有效方法/time 提取是使用 sed 隔离 yyyymmdd_hhmmssSSSS 字符串,然后使用进程替换将隔离的字符串提供给 while 循环进行上述处理。 (唯一的变化是在将 .SSSS 毫秒添加到时间字符串之前检查是否有毫秒 - 在下面的示例中限制为 4 位 - 根据需要添加)

#!/bin/bash

while read line || [ -n "$line" ]; do
    d="${line%_*}"
    d="${d##*_}"    ## trim from left to final '_' isolating date
    d="${d:0:4}-${d:4:2}-${d:6:2}"          ## format date with - between
    t="${line#*_}"
    t="${t##*_}"    ## trim from left to final '_' isolating time
    t="${t:0:2}:${t:2:2}:${t:4:2}"          ## format time with : between
    [ -n "${t:6:4}" ] && t="$t.${t:6:4}"    ## append miliseconds if present
    printf "%s\n\n" "$(date -d "$d $t")"
done < <(sed 's/^[^0-9]*\([0-9][0-9_]*\).*$/\1/' "$1")

输入文件名示例

$ cat file
20181214_195948-ANIMATION.gif
20191012_223451.jpg
IMG_20181122_182138511.jpg
VID_20160909_163547.3gp

示例使用/输出

$ bash extract.sh file
Fri Dec 14 19:59:48 CST 2018

Sat Oct 12 22:34:51 CDT 2019

Thu Nov 22 18:21:38 CST 2018

Fri Sep  9 16:35:47 CDT 2016

这应该涵盖评论中发布的文件名。

关于bash - 从文件名中提取日期子字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58424250/

相关文章:

bash - 如何编写可以通用测试执行命令输出的 Bash 函数?

linux - 像常规命令一样运行脚本

linux - Linux (Bash) 中变量的多路径添加

bash - 使用带有 'rename' 的通配符

linux - 给定列表中最新编辑的文件 SHELL

bash - 使用 ssh 的 TRAMP 不获取 .bash_profile/.profile

bash 文件一个接一个地运行 imacros

linux - 如何使用 %F bash shell 检测文件内容中的日期

bash extglob 范围或值匹配相同的文件名两次

bash - 在kubernetes pod中执行命令(bash脚本)