我有一个这样的文件结构:
- 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
变量塞进(可能不安全的)正则表达式环境中。