web-dev-qa-db-ja.com

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

私はこのようなディレクトリ構造を持っています:

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

Part1.mp3、Part2.mp3などというファイルになりたいです。

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

ある種のfind/xargsコマンドとcutおよびmvを組み合わせてこれを実行できるように感じますが、実際の方法がわかりません。コマンドを形成します。

5
fdmillion

これらの例はどのPOSIXシェルでも機能し、外部プログラムは必要ありません。

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

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

これにより、Part * .mp3ファイルがProjectディレクトリに保持されます。

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

これらのソリューションは、シェルのpattern matchingparameter 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.
11
RobertL

Perl renameprenameと呼ばれることもあります)がある場合は、次のように実行できます。

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

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

rename -n ...を使用して何が起こるかを確認するか、-vの代わりに-nを使用して実行中に発生することを確認します。

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

これは、POSIX paxコマンドラインアーカイバユーティリティを使用して、ツリーのルートで見つかったparent_dirs_base.mp3ごとに、audio.mp3のような名前の現在のディレクトリにハードリンクを作成します/path/to/Project。そうしている間、stderrに対して行ったファイル名の変更を出力します。

-kを使用して、リンクターゲットと同じ名前の既存のファイルが上書きされないようにします。または、実行する前に、まず空のディレクトリに変更します。

私の意見では、操作しようとしているファイルを直接mvするのではなく、最初にハードリンクすることには大きな利点があります。つまり、期待する結果が期待する結果と同じであることを確認する機会が得られます。 get beforeオリジナルを削除します。チェックしたら、次のことができます。

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

...ファイルリンクをクリーンアップして1つ削減します。

3
mikeserv