複数のサブディレクトリのファイル名を変更するには?

複数のサブディレクトリのファイル名を変更するには?

3つのサブディレクトリがあるとしましょう。すべて.というファイルが含まれていますold_file_name。今1つのコマンドで名前をすべてnew_file_name

頑張った

sudo find . -name "old_file_name" -exec rename old_file_name new_file_name {} \;

ただし、次のエラーが表示されます。

'strict subs' (ユーザー提供コードで) を使用する場合、デフォルトの単語 'new_file_name' は使用できません。

答え1

perlこのバリアントは、最初にファイル名とファイルリストを変換するrenameいくつかのコードを引数として使用します。perl

あなたの試みで(コードrenameのファイル引数として見つかったファイルを使用しても効果はありません)、同じように扱われ、これは意味がありません。そうでない場合old_file_nameとして呼び出されます。perluse strict"old_file_name"new_file_namefind

ここでは、次のことができます。

find . -depth -name old_file_name -execdir mv old_file_name new_file_name \;

-execdir標準ではありませんが、かなり一般的です。対照的に-exec、プロセスの現在の作業ディレクトリではなく、選択した各ファイルの親ディレクトリでコマンドを実行しますfind

いいえ-execdir、次のようにできます。

find . -depth -name old_file_name -exec sh -c '
  for file do
    mv "$file" "${file%/*}/new_file_name"
  done' sh {} +

答え2

ここでファイル名を非常に簡単に変換しているのでrename。正確な名前findも使用する必要はないようです。

サブディレクトリが多いと仮定すると、各サブディレクトリにはいくつかのファイルとユーザーhファイルが含まれる場合があります。

各ファイルの名前をにh変更するためのhe最も簡単な解決策は、そのファイルを繰り返してmv新しい名前に変更することです。この場合、e名前に文字を追加するだけで非常に簡単になります。

for name in ./*/h; do
    mv -i "$name" "$name"e
done

これは、パターン拡張によって生成されたすべてのパス名で繰り返されます./*/h。各名前に対して、このコマンドは最後に名前を追加するためにmv -i使用されます。eオプションを使用すると、既存の名前を変更する前に確認メッセージが表示されます-imvmv


質問を更新してから更新してください。

old_file_name各サブディレクトリから呼び出されるすべてのファイルの名前を次のように変更するには、次の手順を実行しますnew_file_name

for name in ./*/old_file_name; do
    mv -i "$name" "${name##*/}/new_file_name"
done

または

for name in ./*/old_file_name; do
    mv -i "$name" "$( dirname "$name" )/new_file_name"
done

両方のループで、ターゲット名は、古いファイル名と同じディレクトリにある新しいファイル名を参照するように計算する必要があります。

最初のループでは、標準変数置換を使用してディレクトリパスを検索します。これにより、最後の項目から最後の項目まですべての項目が${name##*/}削除されます。 2番目のループでは、ほぼ同じことを行うために使用します。次に、結果文字列の最後にフルパス名を追加して新しいファイル名を作成します。$name/dirname "$name"/new_file_name


最後に、Perlrenameユーティリティを使用してください。

rename 's/old_file_name$/new_file_name/' */old_file_name

コマンドの問題は、最初の引数としてPerl式を使用しないことです。このrenameユーティリティはPerl式を使用して与えられたパス名を変換し、それを各パス名に順番に適用します。上記のコマンドでは、単純な代替式を使用して、パス名のファイル名部分を新しいファイル名に置き換えます。

代替エントリはフルパス名を受け取るため、誤ってパス名を変更しないようにするには、文字列の終わり($)と一致する必要があります。目次名前付きパス名にold_file_name

答え3

Stéphane Chazelasの回答に加えて、

引用符を使用する必要があります。ファイル名にスペースが含まれている場合は引用符を使用する必要old_file_nameがあります'old_file_name'。一般的にこのような場合のようです。多くのファイルを扱う場合'{}'の代わりに{}。現時点では、このオプションを使用するときに賞賛を引用することが適切であるかどうかを話すことはできません-execdir

またご確認ください。探すマニュアルページにはセキュリティ警告があるため、この状況に適用されるようです。

関連情報