【问题标题】:Trying to rename files using capture groups in bash尝试使用 bash 中的捕获组重命名文件
【发布时间】:2019-11-01 14:19:19
【问题描述】:

我在 yyyy-MM-dd/img.jpg 格式的文件夹中有一堆来自谷歌外卖的图像文件 - 我使用 phockup 来整理我的照片,它需要将照片放在 yyyy/mm/dd 文件夹中.我想保留日期,因为谷歌已经给了我。

例如 - 这个文件夹/图像应该匹配

/2018-07-01/test_img.jpg

并改名为

/2018/07/01/test_img.jpg

我尝试将 bash 与 sed 一起使用,并找到使用正则表达式捕获组来移动文件,但我似乎运气不佳。请参阅下文了解我目前的位置

find . -name "*.jpg" -print0 | sed 'p;s/([0-9]{4})\-([0-9]{2})\-([0-9]{2})\/(.*)/$2\/$3\/$4\/$5/' | xargs -0 -n2 mv

这是我遇到的错误

mv: 无法将 './2018-07-01/test_img.jpg' 移动到 ''$'\n''./2018-07-01/test_img.jpg': 没有这样的文件或目录

这似乎很奇怪,因为我认为正则表达式捕获组是正确的。我不确定为什么它不会重命名文件。

【问题讨论】:

  • sed 基本正则表达式 不支持出现{n}。请改用sed -r
  • sed -r 's/([0-9]{4})\-([0-9]{2})\-([0-9]{2})\/(.*)/\1\/\2\/\3\/\4/'

标签: regex bash


【解决方案1】:

这是一个 bash 的可能性。在具有日期命名目录的目录中运行脚本。我使用了复制命令而不是移动,因此您可以在删除旧文件之前检查结果。如果您想改用 mv,请至少运行一次,并在其前面加上 echo 以进行完整性检查。

newdir=/home/me/newpics

[[ -d "$newdir"  ]] || mkdir "$newdir"

for dir in *; do
  if [[ -d "$dir" && "$dir" =~ ([0-9]+)-([0-9]+)-([0-9]+) ]]; then
      year=${BASH_REMATCH[1]}
      month=${BASH_REMATCH[2]}
      day=${BASH_REMATCH[3]}

      todir="$newdir/$year"; [[ -d "$todir"  ]] || mkdir "$todir"
      todir+="/$month";      [[ -d "$todir"  ]] || mkdir "$todir"
      todir+="/$day";        [[ -d "$todir"  ]] || mkdir "$todir"

      for file in "$dir/"*.jpg; do
        base=$(basename "$file")
        cp "$file" "$todir/$base"
      done
  fi
done

【讨论】:

  • 谢谢 - 这很有效,并且可能比我尝试使用的充满正则表达式的单行更直接使用
【解决方案2】:

除了我上面的 cmets 之外,要使用 {n} 出现,您需要的不仅仅是 basic 正则表达式,如果我理解正确,您只想将 .jpg 文件与格式匹配,例如/2018-07-01/test_img.jpg,那么您要么需要将 find 表达式限制为仅在日期格式的目录中查找文件,要么您可以让 sed 仅传递这些目录中的文件。 sed 提供了在尝试使用以下形式进行替换之前仅匹配给定格式的行的能力:

sed -r /match/s/find/replace/

(注意:-r 选项会导致 sed 使用 扩展 正则表达式,请查看手册页 (man sed) 以确保您的版本支持选项也是如此,-E 通常用于相同目的)

对于您上面的match,您可以使用:

/^\/[0-9]{4}-[0-9]{2}-[0-9]{2}/

此外,sed-n 选项禁止默认打印输出。因此,要制作一个仅作用于并将适当文件传递给xargs 的表达式,您可以使用以下sed 表达式:

sed -r -n '/^\/[0-9]{4}-[0-9]{2}-[0-9]{2}/s/([0-9]{4})\-([0-9]{2})\-([0-9]{2})\/(.*)/\1\/\2\/\3\/\4/p'

(注意:'$' 替换为\ 以调用所需的反向引用,并将反向引用编号调整为1-4 而不是2-5,并在替换后添加p 会导致sed 打印与表达式匹配的那些行)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-07
    • 2018-01-05
    • 2017-05-30
    • 2019-09-02
    • 2014-10-24
    • 1970-01-01
    • 2020-05-29
    • 2021-09-14
    相关资源
    最近更新 更多