用于递归重命名文件夹的 Bash 脚本

Posted

技术标签:

【中文标题】用于递归重命名文件夹的 Bash 脚本【英文标题】:Bash script to rename folders recursively 【发布时间】:2011-12-25 07:27:30 【问题描述】:

我想重命名我的所有文件夹和这些文件夹中的文件夹,以便文件夹名称中的所有下划线都替换为空格。你能帮我解决这个问题吗?

【问题讨论】:

【参考方案1】:

是的,只需 cd 到 /dir 和 :

find -depth -type d -execdir rename 's/_/ /g'  \;

根据发行版的不同,您需要 perl 重命名(有时是前缀)。

如果

file $(type -p rename)

输出包含 ELF,看起来很糟糕 ;)

编辑 -depth 和 -execdir 添加了

【讨论】:

这不起作用,因为在 find 输出 'foo_bar/baz_quux' 之前将找到并重命名 'foo_bar' - 尝试重命名时将找不到后者。 没什么大不了的,可以加-depth切换查找。 恐怕它仍然不起作用 - 在该示例中要调用的第一个命令是 rename 's/_/ /' ./foo_bar/bar_baz,它会给出错误 Can't rename ./foo_bar/bar_baz ./foo bar/bar_baz: No such file or directory - 如果您使用的是 rename你需要一个正则表达式,它只会替换路径最后一个组件中的下划线。 尝试使用-execdir 而不是-exec 另一个错误是这只会替换目录名称中的第一个下划线 - 请尝试s/_/ /g【参考方案2】:

使用-execdir 的答案更简单,但仅适用于支持-execdirfind 版本,例如GNU find,因为POSIX only specifies -exec

如果您只想使用 bash,那么要正确执行此操作非常棘手,因为您正在重命名 find 正在搜索的目录。即使你得到了正确的顺序,通过使用find-depth 选项,你需要确保只用每个-exec 重写路径的最后一个组件。以下是one of the examples given in the Bash FAQ 的一个简单变体,对我来说似乎没问题:

find . -depth -name "*_*" -exec bash -c 'dir=$1%/* base=$1##*/; mv "$1" "$dir/$base//_/ "' _  \;

该常见问题解答对递归命名文件夹的问题进行了更多讨论,这可能会引起人们的兴趣。


更新:由于那条线相当复杂,为了便于解释,可能值得将其分解一下。本质上,find 命令是:

find . -depth -name "*_*" -exec bash -c [SOME-STUFF] _  \;

也就是说,找到所有包含下划线的目录,对于每个这样的目录,从最深的开始,运行bash脚本[SOME-STUFF],参数0为_(表示我们不关心它)和参数 1 作为找到的文件的名称。 (find 将在-exec 之后用文件名替换\; 只是终止-exec 运行的命令。)

那么[SOME-STUFF]部分是由:

dir=$1%/*

... 使用parameter expansion,将从$1(文件名)的末尾删除/* 的最短匹配,并将dir 设置为结果。同样,这部分:

base=$1##*/

... 从$1 的开头删除*/ 的最长匹配并将base 设置为结果。所以base 只是路径的最后一个组成部分。

那么重命名实际上是通过mv命令完成的,即:

mv "$1" "$dir/$base//_/ "

这再次使用参数扩展,这次使用$parameter/pattern/string 语法。文件名 ($1) 重命名为 $dir,后跟 $base,但 $base 中的每个下划线都替换为空格。

【讨论】:

如果您希望替换值(在本例中为空格)是源自调用脚本的变量怎么办?在前。我已经包含 $SOMEVAR 不起作用。找 。 -depth -name "_" -exec bash -c 'dir=$1%/* base=$1##*/; mv "$1" "$dir/$base//_/$SOMEVAR"' _ \;【参考方案3】:

如果你有 bash4,你可以运行:

for i in **; do [[ -d "$i" ]] || continue; mv "$i" "$i/_/ "; done

【讨论】:

以上是关于用于递归重命名文件夹的 Bash 脚本的主要内容,如果未能解决你的问题,请参考以下文章

Bash 重命名扩展递归

如何在 MacOS 中递归地重命名文件夹和文件

无法重命名文件名

使用 bash 脚本批量重命名 FTP 服务器上的文件

如何使用 bash 脚本重命名当前目录及其子目录中的文件?

我的python脚本以递归方式重命名文件,但失败了