尝试使用bash中的捕获组重命名文件

时间:2019-06-18 21:57:03

标签: regex bash

我从Google外卖中提取了一堆图像文件,格式为yyyy-MM-dd / img.jpg-我使用phockup整理照片,并且需要将照片保存在yyyy / mm / dd文件夹中。我想保留日期,因为Google已经给了他们。

例如-此文件夹/图像应匹配

/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':无此类文件或目录

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

2 个答案:

答案 0 :(得分:1)

这里有重击的可能。在带有日期命名目录的目录中运行脚本。我使用了复制命令而不是移动,因此可以在删除旧文件之前检查结果。如果您想改用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

答案 1 :(得分:0)

除了我上面的评论之外,要使用{n}出现次数,您将需要除 basic 正则表达式之外的其他内容,如果我正确理解,您只想匹配.jpg格式的文件,例如/2018-07-01/test_img.jpg,那么您将需要限制find表达式以仅在日期格式的目录中查找文件,或者可以使sed仅传递那些目录中的文件。 sed可以只匹配给定格式的行,然后尝试使用以下格式进行替换:

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

注意:-r选项使sed使用 extended 正则表达式,请查看手册页(man sed)为了确保您的版本也支持该选项,-E通常用于相同目的)

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

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

此外,-n的{​​{1}}选项禁止输出的默认打印。因此,要制作仅作用于sed并将其传递给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'

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