我希望通过用 Bar 替换字符串的那一部分来递归重命名包含字符串 foo 的所有目录。到目前为止,我已经得到了类似的东西,但它并不是很有效。我也希望 foo 搜索不区分大小写。
find . -type d -exec bash -c 'mv "$1" "${1//foo/Bar}"' -- {} \;
有没有优雅的单行可能比这次尝试更好?我实际上尝试了一些,但我认为我会顺从专家。注意:我在Mac OS X系统上执行此操作,并且没有安装重命名等工具。
答案 0 :(得分:12)
使用参数扩展
尝试以下代码find . -type d -iname '*foo*' -depth -exec bash -c '
echo mv "$1" "${1//[Ff][Oo][Oo]/BAr}"
' -- {} \;
但最好的选择是prename
命令(有时命名为rename
或file-rename
)
find . -type d -iname '*foo*' -depth -exec rename 's@Foo@Bar@gi' {} +
如果您使用bash4
或zsh
(**
表示递归):
shopt -s globstar
rename -n 's@Foo@Bar@gi' **/*foo*/
如果符合您的需要,请移除-n
(干运行)开关以重命名为真实。
某些DOC
rename最初是由Perl的父亲Larry Wall自己编写的。
答案 1 :(得分:6)
我怀疑问题是让它与mkdir -p foo/foo/foo
一起使用。
在这方面,我认为基于find
的解决方案可能不会起作用,因为路径列表可能是预先确定的。
以下绝不是优雅,并且延伸了 one-liner 的定义,但适用于上述测试。
$ mkdir -p foo/foo/foo
$ (shopt -s nullglob && _() { for P in "$1"*/; do Q="${P//[Ff][Oo][Oo]/bar}"; mv -- "$P" "$Q"; _ "$Q"; done } && _ ./)
$ find
.
./bar
./bar/bar
./bar/bar/bar
答案 2 :(得分:5)
find . -type d -iname '*foo*' -exec bash -O nocasematch -c \
'[[ $1 =~ (foo) ]] && mv "$1" "${1//${BASH_REMATCH[1]}/Bar}"' -- {} \;
Pro:避免使用sed Con:如果在不同情况下有多个匹配项,则无法找到所有匹配项 Con:太荒谬了。
答案 3 :(得分:1)
感谢@Gilles Quenot和Wenli:以下内容对我有用。我基于您的两种解决方案。
find . -depth -type d -name 'ReplaceMe*' -execdir bash -c 'mv "$1" "${1/ReplaceMe/ReplaceWith}"' -- {} \;
-execdir
似乎是Linux Red hat 7.6上的关键
答案 4 :(得分:0)
我一直在寻找类似的答案,而且这个答案有效:
find . -depth -name 'foo' -execdir bash -c 'mv "$0" ${0//foo/Bar}"' {} \;