10

文字列のその部分をBarに置き換えることにより、文字列fooを含むすべてのディレクトリの名前を再帰的に変更したいと思います。これまでのところ、このようなものがありますが、うまくいきません。また、 fooをcase-insensitiveで検索したいと思います。

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コマンドです(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必要に応じて、 (dry run) スイッチを削除して実際に名前を変更します。

いくつかのドキュメント

renameは、もともと Perl の父である Larry Wall 自身によって書かれました。

于 2012-10-18T02:03:11.400 に答える
6

問題は、それを で動作させることだと思いmkdir -p foo/foo/fooます。

findこの点で、パスのリストはおそらく事前に決定されているため、に基づくソリューションは機能しない可能性が高いと思います。

以下は決してエレガントではなく、ワンライナーの定義を拡張しますが、上記のテストでは機能します。

$ 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 に答える