find + sed + cpを使用してファイルを見つけ、別の名前のディレクトリにコピーします。

find + sed + cpを使用してファイルを見つけ、別の名前のディレクトリにコピーします。

Folder.jpgというファイルを1つのフォルダにコピーしようとしています。問題は、すべてのファイルの名前が同じであるため、プロセス中に名前を変更する必要があることです。 sedを使用してこれを行うことができることを知っていますが、名前を親フォルダの一部である名前に変更したいと思います。ファイルを見つけてコピーして得た結果です。

cp $(find . -iname "folder.jpg") .albumart/

フォルダ構造は./artist/artist.year.album/folder.jpgで、親フォルダ(またはその一部)を使用してファイル名を指定したいと思います。ライナーの作業を完了するのに役立つ人はいますか?問題をより複雑にするために、一部のフォルダに存在する場合は無視したいCD1およびCD2レイヤーもあります(例:./artist/artist.year.album/CD1/folder.jpg)。

答え1

bashこのバージョンはフォルダ構造(例:)を使用し、./foo/bar/baz/folder.jpgすべてのスラッシュを下線で置き換えます(例:次のようにfoo_bar_baz_folder.jpg)。

find . -iname folder.jpg -exec bash -c 'for x; do x=${x#./}; cp -i "$x" ".albumart/${x//\//_}"; done' _ {} +

何をしても、複数の場所から同じターゲットにファイルを移動するたびに名前がクラッシュする可能性が常にあることに注意してください。

答え2

zshを使う:

autoload zmv
zmv -n -C '(**/)folder.jpg' '.albumart/${1:t}.jpg'

満足のいくものを削除してください-n

これは名前の競合を防ぎます(2つの代替エントリが同じ名前で解決された場合はエラーで失敗します)。例:

$ zmv -n -C '(**/)folder.jpg' '.albumart/${1:t}.jpg'
zmv: error(s) in substitution:
b/c/folder.jpg and a/b/c/folder.jpg both map to .albumart/c.jpg

答え3

出力を解析しないでくださいfind。ファイル名にスペースやグローバル文字が含まれていると?*\[中断されます。を使用している場合は、アクションを介してfindコマンドを呼び出すようにしてください-exec-exec必要な文字列変換を実行するために、操作中にシェルが呼び出されます。

find -name folder.jpg -exec sh -c '
    dir=${0%/*}      # stip off the file name
    case $dir in */CD[0-9]) dir=${dir%/*};; esac
    cp -ip "$0" ".albumart/${dir##*/}.jpg"
' {} \;

ジッシュズマブ通常、これらのコピーを作成する最も簡単な方法は次のとおりです。

zmv -C -o-p -w '**/*.jpg' '.albumart/${${${1%/}/CD<->}##*/}.jpg'

いくつかの説明:

  • 一般的な構文はですzmv OPTIONS… SOURCE_PATTERN REPLACEMENT
  • -wワイルドカードグループの一致を有効にします。代替テキストでは、$1一致する部分**//一致するテキストが空でない場合、つまりファイルが最上位ディレクトリにある場合)を参照し、$2一致する部分を参照します。**.jpg
  • パターンと代替テキストの両方を拡張から保護する必要があります。文字通りに渡す必要がありますzmv
  • 理解するには${${${1%/}/CD<->}##*/}内部から始める必要があります。まず、をインポートして$1最後の項目を削除します/(存在する場合)。最終パターンのマッチングを削除/CD<->(存在する場合)<->1つ以上の数字と一致)。最後に、最後のディレクトリコンポーネントを除くすべてのエントリを閉じます。
  • スペースを下線に置き換えるには、別のレイヤーを追加してくださいパラメータ拡張${${${${1%/}/CD<->}##*/}// /_}

答え4

明らかに、この答えは遅れていましたが、他の人も役に立つと思うかもしれません。

for i in $(find . -type f -iname "folder.jpg" -printf "%P\n") ; do t=$(echo $i | sed 's|/|\.|g'); cp $i TARGETDIR/$t ; done

の目的は、の出力から先行を削除することです-printf "%P\n"./find

find結果($i)をエコーsedし​​て変更します。この場合、sedは/に置き換えられ、.結果全体の値を次に割り当てます。t

次に、見つかったファイル(findこの$i場合)を新しい名前でTARGETDIRにコピーします$t

発見:./artist/artist.year.album/folder.jpg
収率: TARGETDIR/artist.artist.year.album.folder.jpg

関連情報