Bash脚本以递归方式重命名文件夹

use*_*704 4 bash scripting recursion rename

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

Mar*_*air 7

使用的答案-execdir更简单,但只能使用GNU find等find支持的版本-execdir,因为POSIX只能指定-exec.

如果你只是想使用bash,那么要想做到这一点是非常棘手的,因为你正在重命名find正在搜索的目录.即使您通过使用-depth选项获得正确的顺序find,您也需要确保只使用每个组件重写路径的最后一个组件-exec.以下是Bash常见问题解答中给出一个示例的一个微不足道的变体,似乎对我有用:

find . -depth -name "*_*" -exec bash -c 'dir=${1%/*} base=${1##*/}; mv "$1" "$dir/${base//_/ }"' _ {} \;
Run Code Online (Sandbox Code Playgroud)

该FAQ答案有更多关于递归命名文件夹的问题的讨论,这可能是有意义的.


更新:由于这种单线程相当复杂,为了解释起见,可能值得将其分解一点.本质上,find命令是:

find . -depth -name "*_*" -exec bash -c [SOME-STUFF] _ {} \;
Run Code Online (Sandbox Code Playgroud)

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

然后该[SOME-STUFF]部分由以下部分组成:

dir=${1%/*}
Run Code Online (Sandbox Code Playgroud)

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

base=${1##*/}
Run Code Online (Sandbox Code Playgroud)

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

然后重命名实际上是由mv命令完成的,即:

mv "$1" "$dir/${base//_/ }"
Run Code Online (Sandbox Code Playgroud)

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


Gil*_*not 1

是的,只需 cd 到 /dir 并:

find -depth -type d -execdir rename 's/_/ /g' {} \;
Run Code Online (Sandbox Code Playgroud)

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

如果

file $(type -p rename)
Run Code Online (Sandbox Code Playgroud)

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

添加了编辑 -深度和-execdir