Shell 脚本用于根据父文件夹名称重命名多个文件

Shell 脚本用于根据父文件夹名称重命名多个文件

我有一个这样的文件结构:

  • 00000010
    • 000000001.文件1
    • 000000001.文件2
  • 00000020
    • 00000003.文件1
    • 00000003.文件2
    • 00000003.文件3
  • ...

因此,有些文件夹的名称为 8 位数字,其中包含一个或多个名称以 8 位数字开头的文件。但是这些文件名 – 可以说 – 不同步。因此,现在我尝试在 bash 中递归重命名它们以进行存档:

  • 00000010
    • 000000010.文件1
    • 000000010.文件2
  • 00000020
    • 00000020.文件1
    • 00000020.文件2
    • 00000020.文件3
  • ...

我的脚本看起来像:

#! /bin/bash

find * -maxdepth 1 -name "*" -type d | while read -r dir
do
        rename 's/$dir\/[0-9]{8}/$dir/' *
done

但这不起作用并且会出现类似以下错误

全局符号“$dir”需要在第 1 行(eval 1)中明确的包名称。

我该如何编写它来根据文件夹名称重命名文件?

谢谢你的帮助!

答案1

我从另一个答案中了解到,我必须使用

rename "s/$dir\/[0-9]{8}/$dir\/$dir/" $dir/*

以防万一有人遇到同样的问题......

答案2

我不太喜欢$dir将 插入到模式中的答案。如果目录包含被解释为特殊正则表达式标记的字符,则可能会导致意外结果。

我宁愿直接在模式中匹配文件,这样就不需要循环遍历目录,只需使用常规的 glob 即可。

rename 's#([^/]+)/[^/]+(\.file[0-9]+)$#$1/$1$2#' base_directory/*/*

其中 glob 命中目录内的各个文件(它甚至可以指定为base_directory/*/*.file*,或类似的,但在这里并不重要)。

请注意,这是完整的命令,无需构造find

  • 我使用#分隔符而不是“常规”/以避免在模式中转义它。
  • 我捕获了“非目录分隔符”的(贪婪)组,后面跟着目录分隔符,后面跟着文件名和行尾。这使得第一个捕获组成为每个文件的父目录。
  • 文件名的第一部分被丢弃,除了结尾部分以保留序数后缀。

我选择使用一种更通用的方法,而不是假设文件都是 8 个字符长,但真正的区别在于我既不需要构造find也不需要将$dir变量塞进(可能不安全的)正则表达式环境中。

相关内容