【问题标题】:BASH: Get day from dd_mm_yyy at file name with regular expressionBASH:使用正则表达式从 dd_mm_yyy 获取文件名的日期
【发布时间】:2020-02-21 22:14:40
【问题描述】:

我有很多文件(大约 50K),并且需要在创建它们的每一天将它们存储在特定文件夹中。创建日期必须取自它的名称,类似于:

normal_007a02ece6e249d2_940163493_210061_user_sector_23938_22-46-58_2019-12-10-00CA01DF-10270594-00000001.mp3

那里有一些额外的信息,但我必须将其移至文件夹 10,即本月的第 10 天。 所以我有 31 个文件夹 (1-31) 并且必须将每个文件移动到其各自的日文件夹。 任何线索我该怎么做?

编辑: 这就是我正在尝试的:

pattern ='(normal_[A-Za-z0-9].*_[A-Z].*_[0-9]{5}_[0-9]*-[0-9]*-[0-9]*_([0-9]*)-([0-9]*)-([0-9]*).*)'

    for file in *.mp3
    do
       # echo $file

      if [[ $file =~ $pattern ]]; then
            echo "Match ${BASH_REMATCH[0]}"
    fi

提前致谢

【问题讨论】:

  • @Cyrus 这些问题的标题似乎相关,但答案不相关。
  • 不...用户、扇区的值大小不固定,用户可能是“jhon.doper、jhon.doe、jenny.alva 等”,扇区也可能不同。 ..我有这个与文件 normal_[A-Za-z0-9].*_[A-Z].*_[0-9]{5}_[0-9]*-[0-9] 匹配的 RE *-[0-9]*_[0-9]*-[0-9]*-[0-9]*.mp3 但无法弄清楚如何获取大量文件的参数
  • Pluse-uno 用于提高您的 Q....如果您可以确定文件名中唯一的 - 字符在 YYYY-MM-DD 部分中,那么只需 echo "$fName" |sed 's/^.*\([1-2][0-9][0-9][0-9]-[0-1][0-9]-[0-3][0-9]\).*$/\1/' 就可以了日期部分。做你需要的。按照标题dd_mm_yyy 中的描述组织数据是一个令人头疼的问题。您的示例日期是长期存储数据的更好格式。一切都会自然排序,您无需重新解析文件名即可确定您的位置。祝你好运!
  • @JorgeCornejoBellido :是的,我现在看到您的数据确实有其他 -,但除非您的文件名中嵌入了两个(或更多)日期字符串,否则月日的限制(@ 987654328@) 将返回正确的值。我现在使用您提供的样本对其进行了测试,它仅返回 YYYY-MM-DD 值。我还试图指出,当你有复杂的规则要匹配时,试图创建一个完美的正则表达式是很麻烦的,而且通常只关注你确实需要的值更容易实现你的目标。如果这对你不起作用,我理解。祝你好运!

标签: regex linux bash shell


【解决方案1】:

你的模式是错误的。对于您提供的示例,这似乎匹配,但我没有足够的数据来确保:

pattern='normal_[[:xdigit:]]{16}_[[:digit:]]{9}_[[:digit:]]{6}_[^_]*_[^_]*_[[:digit:]]*_[[:digit:]]*-[[:digit:]]*-[[:digit:]]*_([[:digit:]]{4})-([[:digit:]]{2})-([[:digit:]]{2})-[[:xdigit:]]{8}-[[:xdigit:]]{8}-[[:xdigit:]]{8}.mp3'
for file in *.mp3; do [[ $file =~ $pattern ]] && echo ${BASH_REMATCH[1]}/${BASH_REMATCH[2]}/${BASH_REMATCH[3]}; done
2019/12/10
2019/12/13

但是,我的方法会有所不同。 使用 find 查找文件并按顺序生成日期。

for ((i=1;i<=31;i++)) ;
   do 
     DATE=$(date -d "2019-11-30 +$i days" +%Y-%m-%d); 
     find -regextype posix-egrep \
          -iregex '.*normal_[[:xdigit:]]{16}_[[:digit:]]{9}_.*'$DATE'-[[:xdigit:]]{8}-[[:xdigit:]]{8}-[[:xdigit:]]{8}.mp3' 
          -exec echo mv --target-directory=/some/absolute/path/${DATE//-/\/}/ {} +; done


mv --target-directory=/some/absolute/path/2019/12/10/ ./normal_007a02ece6e249d2_940163493_210061_user_sector_23938_22-46-58_2019-12-10-00CA01DF-10270594-00000001.mp3
mv --target-directory=/some/absolute/path/2019/12/13/ ./normal_007a02ece6e249d2_940163493_210061_user_sector_23938_22-46-58_2019-12-13-00CA01DF-10270594-00000001.mp3

简短说明:

  • 这将搜索与包含硬编码的 $DATE 的正则表达式匹配的文件(调整您的开始日期和不同范围的最大值)
  • 使用-exec {} +,它将批量文件移动到一个目录中(为简单起见是同一日期)
  • 当您确实确定结果正常时移除回显。
  • 再次检查正则表达式

编辑:如果您想要一个层次结构(年/月/日),您可以使用模式替换日期(${DATE//-/\/} - 用/ 替换所有破折号),或者直接使用 $i 并限制一个月。

另一种方法是使用 -mtime/-ctime 代替实际日期。

【讨论】:

  • 谢谢!我的目标只是获得日期(1-31)而不是日期为 yyyy-mm-dd,我将模式调整为 pattern='normal_[[:xdigit:]]{16}_[[:digit:]] {9}_[[:digit:]]{6}_[^_]*[^]*_[[:digit:]]*_[[:digit:]]*- [[:digit:]]*-[[:digit:]]*_[[:xdigit:]]{4}-[[:xdigit:]]{2}-(.*)-[[:xdigit: ]]{8}-[[:xdigit:]]{8}-[[:xdigit:]]{8}.mp3'
  • 我需要一天,因为这些文件已经具有 yyyy > mm 的文件夹结构,但这会导致性能问题,所以现在我们还将分为 days yyyy > mm > dd 子文件夹。跨度>
【解决方案2】:

要提取dddd-dd-dd 形式的字符串,其中d 是一个数字,您可以使用GNU grep。然后你可以将日期读入ymd变量:

str=$(grep -Po "\d{4}-\d{2}-\d{2}" <(echo normal_2019-12-10-00.mp3))
read y m d < <(date -d $str "+%Y %m %d")
echo $y.$m.$d
2019.12.10

从字符串中提取像yyyy-mm-dd 这样的日期需要更复杂的正则表达式,如“Regex to validate date format dd/mm/yyyy”中所述

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-30
    • 2020-03-31
    • 1970-01-01
    • 2012-10-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多