【发布时间】:2023-06-20 10:06:02
【问题描述】:
我想重命名我的所有文件夹和这些文件夹中的文件夹,以便文件夹名称中的所有下划线都替换为空格。你能帮我解决这个问题吗?
【问题讨论】:
标签: bash scripting recursion rename
我想重命名我的所有文件夹和这些文件夹中的文件夹,以便文件夹名称中的所有下划线都替换为空格。你能帮我解决这个问题吗?
【问题讨论】:
标签: bash scripting recursion rename
是的,只需 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。
使用-execdir 的答案更简单,但仅适用于支持-execdir 的find 版本,例如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 中的每个下划线都替换为空格。
【讨论】:
如果你有 bash4,你可以运行:
for i in **; do [[ -d "$i" ]] || continue; mv "$i" "${i/_/ }"; done
【讨论】: