あなたのfind
使い方には問題があります。最初のオプションは検索の開始位置であるため、そこでグロブを使用したくありません。そのサブディレクトリのファイルのみが必要な場合は、Olaf が提案したtest/
ように、オプションを使用します。-depth
この名前変更を処理するために別のスクリプトを使用する必要はありません。find
少し面倒なことを気にしなければ、コマンド ライン内で実行できます。
最上位のファイルのみを処理するには、次のようにします。
$ touch foo.txt bar.txt baz.ext
$ find test -depth 1 -type f -name \*.txt -exec bash -c 'f="{}"; mv -v "{}" "${f/.txt/.csv}"' \;
./foo.txt -> ./foo.csv
./bar.txt -> ./bar.csv
$
しかし、あなたの懸念は有効です -find
は一致のリストを作成します-exec
。リストを下からfind
変更すると、一部の名前変更が失敗します。
あなたの最も簡単な解決策は、これを2つの段階(複数ではない)で行うことだと思います.1つはファイル用、もう1つはディレクトリ用です。(または順序を変更します。問題ではないと思います。)
$ mkdir foo_1; touch red_2 foo_1/blue_3
$ find . -type f -name \*_\* -exec bash -c 'f="{}"; mv -v "{}" "${f%_?}X${f##*_}"' \;
./foo_1/blue_3 -> ./foo_1/blueX3
./red_2 -> ./redX2
$ find . -type d -name \*_\* -exec bash -c 'f="{}"; mv -v "{}" "${f%_?}X${f##*_}"' \;
./foo_1 -> ./fooX1
Bash のパラメーター展開は、長い道のりを歩むことになります。
の実装に応じて、次find
のオプションがあり-d
ます。
-d Cause find to perform a depth-first traversal, i.e., directories
are visited in post-order and all entries in a directory will be
acted on before the directory itself. By default, find visits
directories in pre-order, i.e., before their contents. Note, the
default is not a breadth-first traversal.
そう:
$ mkdir -p foo_1/bar_2; touch red_3 foo_1/blue_4 foo_1/bar_2/green_5
$ find . -d -name \*_\* -exec bash -c 'f="{}"; mv -v "{}" "${f%_?}X${f##*_}"' \;
./foo_1/bar_2/green_5 -> ./foo_1/bar_2/greenX5
./foo_1/bar_2 -> ./foo_1/barX2
./foo_1/blue_4 -> ./foo_1/blueX4
./foo_1 -> ./fooX1
./red_3 -> ./redX3
$