2012-10-18 21 views
9

fooの文字列を含むすべてのディレクトリの名前を、Barに置き換えて再帰的に名前を変更したいとします。私はこれまでのようなものを持っていますが、それはうまくいきません。また、fooを検索したいと思います。大文字と小文字を区別しないbashのディレクトリ名を再帰的に変更する

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

この試みよりも良いかもしれない任意のエレガントなワンライナーはありますか?私は実際にいくつかを試しましたが、私は専門家に延期すると思っていました。注:私はMac OS Xシステムでこれをやっていて、の名前をのようにインストールしていません。

+0

を、あなたはエラーを持っていますか? –

+0

1タイマーの場合は、ワンライナーである必要はありません:) – user1154664

答えて

11

パラメータ展開

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

を使用して、次のコードを試してみてくださいしかし、あなたの最善の策は、

find . -type d -iname '*foo*' -depth -exec rename '[email protected]@[email protected]' {} + 

(時々renameまたはfile-renameという名前)prenameコマンドになりますそして、あなたはbash4を使用している場合、またはzsh**平均再帰):

shopt -s globstar 
rename -n '[email protected]@[email protected]' **/*foo*/ 

必要に応じて、-n(ドライラン)スイッチを取り外して、実際の名前に変更します。

renameは、もともとPerlのお父さん、Larry Wall氏自身によって書かれたSOME DOC。

+2

秘密、醜い、そして華麗 –

+0

@putnick - ['sed'版を削除するとうれしくアップウィートします。] http://mywiki.wooledge.org/ParsingLs) – ghoti

+0

サブディレクトリを最初に処理する '-depth'が追加されました –

5
find . -type d -iname '*foo*' -exec bash -O nocasematch -c \ 
    '[[ $1 =~ (foo) ]] && mv "$1" "${1//${BASH_REMATCH[1]}/Bar}"' -- {} \; 

プロ:はSED回避できます。
Con:異なる場合が複数ある場合、すべての一致が見つかりません。
Con:ばかげています。

+0

OPでは大文字と小文字を区別しない置換が必要です。 –

+0

'-name'は" * FOO * "と一致しません –

+0

** + 1 ** - これはうまくいくようです。そして、はい、少しばかげています。 :-) – ghoti

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 
+0

** + 1 ** - 優秀な点です。秘密のbashの使用。よくやった。 :) – ghoti

0

私は同様の答えを検索してきたし、この1つは働いた:

find . -depth -name 'foo' -execdir bash -c 'mv "$0" ${0//foo/Bar}"' {} \; 
関連する問題