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

时间:2011-11-09 13:02:28

标签: bash scripting recursion rename

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

3 个答案:

答案 0 :(得分:7)

使用-execdir的答案更简单,但仅适用于支持find的{​​{1}}版本,例如GNU find,POSIX only specifies -exec

如果您只想使用bash,那么要想做到这一点非常棘手,因为您要重命名-execdir正在搜索的目录。即使您通过使用find -depth选项获得正确的订单,也需要确保只使用每个find重写路径的最后一个组件。以下是one of the examples given in the Bash FAQ的一个微不足道的变体,似乎对我有用:

-exec

该FAQ的答案更多地讨论了可能感兴趣的递归命名文件夹的问题。


更新:由于这种单线程相当复杂,为了解释起见,可能值得将其分解一下。基本上,find . -depth -name "*_*" -exec bash -c 'dir=${1%/*} base=${1##*/}; mv "$1" "$dir/${base//_/ }"' _ {} \; 命令是:

find

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

然后-exec部分由:

组成
[SOME-STUFF]

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

dir

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

然后重命名实际上由base命令完成,即:

mv

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

答案 1 :(得分:1)

是的,只需cd到/ dir和:

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

根据发行版,您需要perl重命名(有时是prename)。

如果

file $(type -p rename)

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

修改  -depth和-execdir添加了

答案 2 :(得分:0)

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

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