親ディレクトリに基づいてファイル名を変更するには、find / xargsコマンドを使用しますか?

親ディレクトリに基づいてファイル名を変更するには、find / xargsコマンドを使用しますか?

次のディレクトリ構造があります。

Project/
  |
  +--Part1/
  |    |
  |    +--audio.mp3
  |
  +--Part2/
  |    |
  |    +--audio.mp3
  |
  +--Part3/
  |    |
  |    +--audio.mp3
...

Part1.mp3、Part2.mp3などのファイルにしたいです。

各フォルダには1つのファイルしか含まれていないため、ファイルが破損したり、同じ名前の複数のファイルを処理したりする危険はありません。

find一種の/xargsコマンドプラスとを使用してcutこれを行うことができるようですが、mv実際にコマンドを設定する方法がわかりません。

答え1

これらの例はすべてのPOSIXシェルで実行でき、外部プログラムは必要ありません。

これにより、Part * .mp3ファイルがプロジェクトディレクトリと同じレベルに保存されます。

(cd Project && for i in Part*/audio.mp3; do echo mv "$i" ../"${i%/*}".mp3; done)

これにより、プロジェクトディレクトリにPart * .mp3ファイルが残ります。

for i in Project/Part*/audio.mp3; do echo mv "$i" ./"${i%/*}".mp3; done

これらのソリューションはシェルを使用してpattern matching parameter expansion新しいファイル名を生成します。

 ${parameter%word}     Remove Smallest Suffix Pattern.  The word is expanded
                       to produce a pattern.  The parameter expansion then
                       results in parameter, with the smallest portion of
                       the suffix matched by the pattern deleted.

答え2

renamePerl(時々呼び出される)がある場合は、prename次のことができます。

( cd Project && rename 's!(.+)/(.+)(\.mp3)!$1.$3!' */audio.mp3 )

これは、シェルグローブと一致するすべてのファイル名を取得し、*/audio.mp3それをディレクトリ、ファイル名、および拡張コンポーネントに分割します。次に、ファイル名の部分を破棄し、ファイル名を変更します。

rename -n ...何が起こるのかを確認するために使用するか、実行時に何が起こるのかを確認するため-vに代わりに使用します。-n

答え3

pax -rwls'|.*/\(.*\)/audio\(\.mp3\)$|\1\2|p' \
    -s'|.*||' /path/to/Project .

これは、POSIXコマンドラインアーカイブユーティリティを使用して、ツリーで見つかった各ルートディレクトリの名前付きpax現在のディレクトリにハードリンクを作成します。parent_dirs_base.mp3audio.mp3/path/to/Project。これにより、stderrのファイル名の変更がすべて印刷されます。

-kリンク先と同じ名前の既存のファイルを潜在的に上書きするのを防ぐため、またはより良い方法で実行する前に最初に空のディレクトリに変更するのを防ぐために使用されます。

mv私の考えでは、使用したいファイルを直接リンクするのではなく、最初にハードリンクを作成することに大きな利点があります。つまり、期待する結果が得られる結果と同じであることを確認する機会があるということです。今後原稿を削除してください。確認後、次のことができます。

find /path/to/Project -name audio.mp3 -exec rm {} +

...ファイルリンクを整理して1つずつ減らしてください。

答え4

Perlの味を使ったBash

for file in `find . -type f -name "*.mp3"`;
    do
        dir=$(dirname $file);
        bdir=$(basename $dir);
        bname=$(basename $file);
        new=$bdir.$bname;
        newname=${new//\.\./};
        newname_with_path=$dir/$newname
        if [ "$file" != "$newname_with_path" ]
        then
            echo mv -u $file  $newname_with_path ;
        fi
    done


    # replace 2 dots with nothing
    # bash 4.1.2 centos 6.4 no problem with or without bashslash
    newname=${new//../};

関連情報