Camelcased ファイルの名前をスペースを含むように一括変更します。

Camelcased ファイルの名前をスペースを含むように一括変更します。

隣接する大文字と小文字の間にスペースを含めるように、camelCaseファイルの名前を一括変更しようとしています。私はMac OSを使用しているので、私が使用するユーティリティはBSDのバリエーションです。

たとえば、

250 - ErosPhiliaAgape.mp3 => 250 - Eros Philia Agape.mp3

find次のコマンドを使用して、関連ファイルをサブシェルでmv実行されているファイルにパイプしようとします。sed

find . -name "*[a-z][A-Z]*" -print0 | xargs -0 -I {} mv {} "$(sed -E 's/([a-z])([A-Z])/\1 \2/g')"

このコマンドだけでも正常に動作します。find正しいファイルを抽出してsed名前を正しく変更しましたが、xargsと組み合わせると何も起こりません。

これを行うには何を変更する必要がありますか?

答え1

問題は、コマンドのサブシェルがファイル単位では$(...)なく、コマンドが実行されたときに評価されることです。 'sをxargs使用して、a内の各ファイルのコマンド数を計算し、参照を適切に置き換えることができます。find-execsh

find . -name "*[a-z][A-Z]*" -type f -exec sh -c 'echo mv -v "{}" "$(echo "{}" | sed -E "s/([a-z])([A-Z])/\1 \2/g")"' \;

この出力が良好に見える場合は、echoinを削除してくださいecho mv。 .echo | sed\n

答え2

あなたのsedコマンドはパイプから入力を受けています。と競合するため、xargs2つのコマンドのそれぞれは、で作成されたデータの一部を取得しfind(各バイトは1つのリーダーにのみ送信されます)、どのコマンドが何を受け取るかを予測する方法はありません。

各ファイル名をにパイプする必要がありますsed。つまり、パイプを設定するには中間シェルが必要です。

find . -name "*[a-z][A-Z]*" -print0 | xargs -0 -I {} sh -c 'mv "$0" "$(echo "$0" | sed -E '\''s/([a-z])([A-Z])/\1 \2/g'\'')"' {}

その必要はありませんxargs。デフォルトでは役に立たない。findプログラムを直接呼び出すことができます。

find . -name "*[a-z][A-Z]*" -exec sh -c 'mv "$0" "$(echo "$0" | sed -E '\''s/([a-z])([A-Z])/\1 \2/g'\'')"' {} \;

または、インストールするrename次のPerlの実装File::RenameまたはUnicode::Tussle

cpan File::Rename
find -depth . -exec rename 's!([a-z])([A-Z])(?!.*/)!$1 $2!g' {} +

この(?!.*/)ビットは、ディレクトリ名にcamelCaseが含まれている場合にディレクトリ名で置換がトリガーされるのを防ぎます。ディレクトリの名前が変更された場合は、ディレクトリを巡回した後にこれが発生するように渡さ-depthれます。findfind

答え3

GNU Parallelを使用する場合は、解決策は次のとおりです。

find . -name "*[a-z][A-Z]*" -type f | parallel mv -v {} '{= s:([a-z])([A-Z])(?!.*/):$1 $2:g =}'

関連情報