10

我想通过用Bar替换字符串的那部分来递归地重命名包含字符串foo的所有目录。到目前为止,我有类似的东西,但它并不完全有效。我也希望foo被搜索不区分大小写

find . -type d -exec bash -c 'mv "$1" "${1//foo/Bar}"' -- {} \;

有没有可能比这次尝试更好的优雅单线?我实际上已经尝试了一些,但我认为我会听从专家的意见。注意:我在 Mac OS X 系统上执行此操作,并且没有安装重命名等工具。

4

5 回答 5

13

使用参数扩展尝试以下代码

find . -type d -iname '*foo*' -depth -exec bash -c '
    echo mv "$1" "${1//[Ff][Oo][Oo]/BAr}"
' -- {} \;

但是您最好的选择是prename命令(有时命名为renameor file-rename

find . -type d -iname '*foo*' -depth -exec rename 's@Foo@Bar@gi' {} +

如果你使用bash4or zsh**意思是递归):

shopt -s globstar
rename -n 's@Foo@Bar@gi' **/*foo*/

如果它符合您的需要,请移除-n(试运行)开关以真正重命名。

一些文档

rename最初是由 Perl 的父亲 Larry Wall 自己编写的。

于 2012-10-18T02:03:11.400 回答
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
于 2012-10-18T02:30:19.860 回答
5
find . -type d -iname '*foo*' -exec bash -O nocasematch -c \
    '[[ $1 =~ (foo) ]] && mv "$1" "${1//${BASH_REMATCH[1]}/Bar}"' -- {} \;

优点:避免使用 sed。
缺点:如果在不同情况下有多个匹配项,则不会找到所有匹配项。
缺点:很荒谬。

于 2012-10-18T02:03:30.793 回答
2

感谢@Gilles Quenot 和 Wenli:以下内容对我有用。我基于您的两个解决方案。

find . -depth -type d -name 'ReplaceMe*'  -execdir bash -c 'mv "$1" "${1/ReplaceMe/ReplaceWith}"' -- {} \;

-execdir似乎是 linux Red hat 7.6的关键

于 2019-08-07T15:26:21.167 回答
1

我一直在寻找类似的答案,这个答案有效:

find . -depth -name 'foo' -execdir bash -c 'mv "$0" ${0//foo/Bar}"' {} \;
于 2017-10-27T15:09:12.717 回答