我想将所有包含“特殊”一词的文件和目录重命名为“常规”。它应该保持区分大小写,因此“特殊”不会变成“常规”。
我怎样才能在bash中递归地做到这一点?
使用的解决方案find
:
仅重命名文件:
find /your/target/path/ -type f -exec rename 's/special/regular/' '{}' \;
仅重命名目录:
find /your/target/path/ -type d -execdir rename 's/special/regular/' '{}' \+
要重命名文件和目录:
find /your/target/path/ -execdir rename 's/special/regular/' '{}' \+
尝试这样做(要求bash --version
> = 4):
shopt -s globstar
rename -n 's/special/regular/' **
当您的测试正常时移除-n
开关
还有其他同名的工具可能会也可能不会这样做,所以要小心。
如果您运行以下命令 ( GNU
)
$ file "$(readlink -f "$(type -p rename)")"
你有一个像
.../rename: Perl script, ASCII text executable
并且不包含:
ELF
那么这似乎是正确的工具=)
如果不是,则使其成为默认值(通常已经如此)Debian
和衍生,例如Ubuntu
:
$ sudo update-alternatives --set rename /path/to/rename
(替换/path/to/rename
为您的perl's rename
命令的路径。
如果您没有此命令,请搜索您的包管理器进行安装或手动执行
最后但同样重要的是,这个工具最初是由 Perl 的父亲 Larry Wall 编写的。
如果您不介意安装另一个工具,那么您可以使用rnm:
rnm -rs '/special/regular/g' -dp -1 *
它将遍历所有目录/子目录(因为)并在其名称中用常规-dp -1
替换特殊。
@speakr 的回答是我的线索。
如果使用 -execdir 来转换文件和目录,您还需要-type f
从所示示例中删除。要拼写出来,请使用:
find /your/target/path/ -execdir rename 's/special/regular/' '{}' \+
g
此外,如果要替换给定文件名中所有出现的special
withregular
而不仅仅是第一次出现,请考虑向正则表达式添加(全局)标志。例如:
find /your/target/path/ -execdir rename 's/special/regular/g' '{}' \+
将转变special-special.jpg
为regular-regular.jpg
. 没有全局标志,你最终会得到regular-special.jpg
.
仅供参考:默认情况下,Mac OSX 上未安装 GNU Rename。如果您使用的是Homebrew 包管理器,brew install rename
将对此进行补救。
正如 Rui Seixas Monteiro 所提到的,最好将 -iregex 模式选项与 Find 命令一起使用。我发现了以下作品,并在 U007D 提到的正则表达式中包含了全局标志:
文件:
查找 /path/ -type f -iregex '.*special.*' -execdir rename 's/special/regular/g' '{}' \+;
目录:
查找 /path/ -type d -iregex '.*special.*' -execdir rename 's/special/regular/g' '{}' \+;
文件和目录
查找 /path/ -iregex '.*special.*' -execdir rename 's/special/regular/g' '{}' \+;
这是另一种更便携且不依赖于rename
命令的方法(因为它可能需要不同的参数,具体取决于发行版)。
它递归地重命名文件和目录:
find . -depth -name "*special*" | \
while IFS= read -r ent; do mv $ent ${ent%special*}regular${ent##*special}; done
它能做什么
-depth
参数的 find 通过执行深度优先遍历来重新排序结果(即目录中的所有条目都显示在目录本身之前)。这样,文件首先被修改,然后是每个父目录。
例子
给出以下树:
├── aa-special-aa
│ └── bb-special
│ ├── special-cc
│ ├── special-dd
│ └── Special-ee
└── special-00
它按特定顺序生成这些mv
命令:
mv ./aa-special-aa/bb-special/special-cc ./aa-special-aa/bb-special/regular-cc
mv ./aa-special-aa/bb-special/special-dd ./aa-special-aa/bb-special/regular-dd
mv ./aa-special-aa/bb-special ./aa-special-aa/bb-regular
mv ./aa-special-aa ./aa-regular-aa
mv ./special-00 ./regular-00
获取以下树:
├── aa-regular-aa
│ └── bb-regular
│ ├── regular-cc
│ ├── regular-dd
│ └── Special-ee
└── regular-00
对于那些只想重命名目录的人,您可以使用以下命令:
find /your/target/path/ -type d -execdir rename 's/special/regular/' '{}' \;
Note 类型现在d
用于目录,并使用-execdir
.
不过,我还没有弄清楚如何一次性重命名文件和目录。
早些时候有人评论说,一旦它重命名了根文件夹,它就不能再遍历文件树了。有一个可用的-d
开关可以从下到上进行深度遍历,所以我相信根会最后重命名:
find -d /your/target/path/ -type d -execdir rename 's/special/regular/' '{}' \;
从手册页(man find
):
-d Cause find to perform a depth-first traversal, i.e., directories are visited in post-order and all entries in a directory will be
acted on before the directory itself. By default, find visits directories in pre-order, i.e., before their contents. Note, the
default is not a breadth-first traversal.
对于rename
版本rename from util-linux 2.23.2
,以下命令对我有用:
find . -type f -exec rename mariadb mariadb-proxy '{}' \;