정규식을 기반으로 음악 앨범 폴더의 이름을 일괄적으로 바꾸는 셸 코드 한 줄 - "zsh: '+' 뒤에 식별자가 누락되었습니다."

정규식을 기반으로 음악 앨범 폴더의 이름을 일괄적으로 바꾸는 셸 코드 한 줄 - "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

나는 껍질에 대한 경험이 거의 없습니다. 여기나 다른 곳에서 도움을 요청하면 다음과 같이 할 수 있지만 불완전하게 한 줄로 작성됩니다("에코"는 이름을 바꾸기 전 테스트를 위한 것이며 잠재적인 지옥을 피하기 위해 여기에도 가독성을 위해 몇 가지를 다시 기록했습니다).

% 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에서 더 이상 사용되지 않는 명령 대체 형식이며 현대 $(...)형식(from 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 표현식을 인용하려면 역따옴표(`) 대신 작은따옴표(')를 사용하세요.

관련 정보