正規表現に基づいて音楽アルバムフォルダの名前を一括変更するシェルコードの1行 - "zsh:'+'の後に識別子がありません。"

正規表現に基づいて音楽アルバムフォルダの名前を一括変更するシェルコードの1行 - "zsh:'+'の後に識別子がありません。"

私の音楽ライブラリには以下が含まれます。次のパターンで名前が付けられたフォルダ :

METAGENRE - Subgenre(s) - ARTIST - Album (year)

アルバム全体を保持している一部のバンド/アーティストのフォルダ名で、年とアルバム「ラベル」を切り替えて、アルバム名ではなくリリース時間を基準にソートしたいと思います。同時に、年ラベルの周りの括弧を削除することもできます。例:

METAGENRE - Subgenre(s) - ARTIST - year Album

たとえば、METAL - Black, Français - PESTE NOIRE - Split (2018)

次のようにする必要があります。METAL - Black, Français - PESTE NOIRE - 2018 Split

私はシェルの経験はほとんどありません。ここや他の場所で助けを求めることは次のようにすることができますが、不完全に1行で書かれます(「エコ」は名前を変更する前のテストのためのものであり、潜在的な地獄を避けるためにここでも読みやすさのためにいくつか書き直しました) 。

% for f in *PESTE\ NOIRE* ;
do echo
     mv "$f"
     "$(echo $f | sed `s/- ([A-Za-z]+) \(([0-9]{4})\)$/- \2 \1/p`)"
     ;
done

端末でこのコマンドを実行すると、次のような結果が得られます。 zsh: missing identifier after `+'

私は何が間違っていましたか?

編集:(「引用符の代わりに」を使用)

% for f in *PESTE\ NOIRE* ; do echo mv "$f" "$(echo $f | sed 's/- ([A-Za-z]+) \(([0-9]{4})\)$/- \2 \1/')" ; done

動作しますが、もう別のエラーが発生します。

sed: 1: "s/- ([A-Za-z]+) \(([0-9 ...": \2 not defined in the RE

したがって:

% for f in *PESTE\ NOIRE* ; do echo mv "$f" "$(echo $f | sed 's/- \([A-Za-z]+\) \\\(\([0-9]{4}\)\\\)$/- \2 \1/')" ; done

エラーは返されませんが、フォルダ名は変更されていません。

答え1

では、次のようにファイル名を変更zshできます。zmv

autoload -Uz zmv # best in ~/.zshrc
zmv -n '(*PESTE NOIRE*-)(*) \((<1900-2100>)\)' '$1 $3$2'

実際にこれを行うには、削除-n(テスト実行)してください。

コードに関するいくつかの問題:

  • `...`sh / cshで使用されなくなったコマンドの代替形式であり、現代の$(...)形式kshと同様に引用が必要です。しかし、それ自体は多くの問題があるため、使用しないでください。いずれにせよ、テキストの引用には使用されず、特定のコマンドの出力を拡張するためにのみ使用されます。またはなどの文字をsed含む傾向があるコードの場合、最良の引用符は一重引用符()であり、Bourneなどのシェル(zshを含む)では、シェルはどの文字も特に処理しません。\$'...'
  • 一部のテキストをそのまま印刷するにはprint -r - $f(kshスタイル、kshに引用符が必要です)、またはprintf '%s\n' $f(POSIXスタイル、shにも引用符が必要です)、またはecho -E - $f(-特定)を使用してバックスラッシュで始まる値を含めないでzshください。ここで文字列構文も参照してください。echo $f$f-<<< $f
  • +{4}および(...)拡張(またはPerl)正規表現演算子であるため、サポートされている-E場合はor、-Pオプションが必要ですsed。基本的な正規表現は\{1,\}\{4\}および\(...\)(あなたが\2一致しない理由を説明します)です。いくつかのsed実装では\+
  • [A-Za-z]Ased 実装によっては、間に並べられた文字と一致するか、一致しない場合があります。Zまたはazshは独自のglobと一致しません。並べ替えて除外できます。他のテキストの文字も同じです。文字(またはより一般的には人間の言語の単語に含まれる文字)を一致させるために使用されます。たくさんzçœźz[[:alpha:]]アルバムスペースや数字がある可能性があり.'...[^-]以外の文字には-より良いアプローチがあります。または、上記のように古いコンテンツが貪欲であるというzmv事実に依存します。*
  • sedこれは行ベースとテキストベースであるため、ファイル名が完全に処理されず、ファイル名の各行が別々に処理されることに注意してください(エンコーディング内の改行や文字以外の行を含む行のみ)。ロケールの文字セット外のファイル名に問題があります。
  • --コマンド引数に変数データを使用する場合は、オプションの終わりを表示する必要があります。で始まる場合はmv $f ...オプションと見なされます。$f-

したがって、必ず使用する必要がある場合sed(しかし確かにzshでは使用しない)、これらの問題を解決する方法は次のとおりです。

for old in *'PESTE NOIRE'*; do
  new=$(print -r - $f | sed  '
    :1
    $!{
      N;b1
    }
    s/\(.*-\)\(.*\) ([[:digit:]]\{4\})$/\1 \3\2/'
  ) && [[ $old != $new ]] &&
    mv -i -- $old $new
done

答え2

sed式を引用するには、逆引用符(`)の代わりに一重引用符(')を使用してください。

関連情報