1

フォルダーとファイルの名前を変更する for ループを使用するスクリプトがあります。スクリプトは、ファイルとフォルダーのリストを取得し、条件付きで名前を変更します。次のコマンドを使用してファイルを呼び出します。

find test/* -exec ./replace.sh {} \;

私の replace.sh スクリプトには、次のようなものが含まれます。

for i in $@
mv $OLDFILE $NEWFILE
done

$OLDFILE と $NEWFILE は以前に設定されており、問題は発生しないと思います。

サブディレクトリに出くわしたときに問題が発生します。もともと、次のようなフォルダーがあります。

folder_1

 -file1

 -file2

私のスクリプトが folder_1 を folderX1 に変更すると、変更されたパスが folderX1/file1 になるため、次の引数 folder_1/file1 は無効になります。変更中のフォルダーのリストを含むスタックを作成し、後でそれらをポップアウトしてファイルの名前を変更できると考えましたが、これは bash では難しいようです。私が見逃しているより良い方法はありますか?

PS プログラムを数回実行してすべてのサブディレクトリを調べることもできますが、これは効率的ではないようです。

4

2 に答える 2

1

あなたの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
$ 
于 2013-04-13T00:17:30.230 に答える