디버깅 전용 bash 스크립트

디버깅 전용 bash 스크립트

파일 이름에서 문자를 제거하려고 합니다.

문서

#ls
Peter, Paul & Mary - The Very Best of Peter, Paul and Mary (AutoFlac).flac
Peter, Paul & Mary - The Very Best of Peter, Paul and Mary (AutoFlac).log
Peter, Paul & Mary - The Very Best of Peter, Paul and Mary.cue

내가 원하는 출력은 다음과 같습니다.

#ls
Peter, Paul & Mary - The Very Best of Peter, Paul and Mary.cue
Peter, Paul & Mary - The Very Best of Peter, Paul and Mary.flac
Peter, Paul & Mary - The Very Best of Peter, Paul and Mary.log

스크립트

#!/bin/bash
SUFFIX="(AutoFLAC)"
#search directory for file with a suffix of (AutoFLAC)
for entry in *$SUFFIX*
do
   #remove a leading space and (AutoFLAC) from the file name
   FILENAME=`echo $entry | sed 's/ (AutoFLAC)//'`
   echo "$entry"
   echo "$FILENAME"
   #change the old file name for the new file name
   mv  "$entry" "$FILENAME"
 done

추가하면 -x작동합니다.

Mac-Attack:edit-file-names $ ./edit-file-names1.sh 
+ SUFFIX='(AutoFLAC)'
+ for entry in '*$SUFFIX*'
++ echo Peter, Paul '&' Mary - The Very Best of Peter, Paul and Mary '(AutoFLAC).flac'
++ sed 's/ (AutoFLAC)//'
+ FILENAME='Peter, Paul & Mary - The Very Best of Peter, Paul and Mary.flac'
+ echo 'Peter, Paul & Mary - The Very Best of Peter, Paul and Mary (AutoFLAC).flac'
Peter, Paul & Mary - The Very Best of Peter, Paul and Mary (AutoFLAC).flac
+ echo 'Peter, Paul & Mary - The Very Best of Peter, Paul and Mary.flac'
Peter, Paul & Mary - The Very Best of Peter, Paul and Mary.flac
+ mv 'Peter, Paul & Mary - The Very Best of Peter, Paul and Mary (AutoFLAC).flac' 
'Peter, Paul & Mary - The Very Best of Peter, Paul and Mary.flac'
+ for entry in '*$SUFFIX*'
++ echo Peter, Paul '&' Mary - The Very Best of Peter, Paul and Mary '(AutoFLAC).log'
++ sed 's/ (AutoFLAC)//'
+ FILENAME='Peter, Paul & Mary - The Very Best of Peter, Paul and Mary.log'
+ echo 'Peter, Paul & Mary - The Very Best of Peter, Paul and Mary (AutoFLAC).log'
Peter, Paul & Mary - The Very Best of Peter, Paul and Mary (AutoFLAC).log
+ echo 'Peter, Paul & Mary - The Very Best of Peter, Paul and Mary.log'
Peter, Paul & Mary - The Very Best of Peter, Paul and Mary.log
+ mv 'Peter, Paul & Mary - The Very Best of Peter, Paul and Mary (AutoFLAC).log' 'Peter, Paul & Mary - The Very Best of Peter, Paul and Mary.log'
Mac-Attack:edit-file-names $ ls
Peter, Paul & Mary - The Very Best of Peter, Paul and Mary.cue
Peter, Paul & Mary - The Very Best of Peter, Paul and Mary.flac
Peter, Paul & Mary - The Very Best of Peter, Paul and Mary.log

아니요 -x:

Mac-Attack:edit-file-names $ ./edit-file-names2.sh 
*(AutoFLAC)*
*(AutoFLAC)*
mv: rename *(AutoFLAC)* to *(AutoFLAC)*: No such file or directory

통찰력, 생각?

답변1

대소문자를 구분하지 않는 와일드카드 일치에는 분명히 이상한 상황이 있습니다. ls출력 에 따르면 파일 이름에는 (AutoFlac)가 포함되어 있지만 스크립트는 (AutoFLAC). 전통적으로 Unix 도구는 바이트 단위로 동일한 두 파일 이름만 동일한 것으로 간주합니다. 대소문자를 구분하는 일치 기능이 내장되어 있지 않습니다. Bash는 대소문자를 구분하지 않는 파일 시스템에서 일관되지 않게 작동하는 것으로 보이며 이는 버그일 수 있습니다.

변수 대체에 큰따옴표를 사용하면 스크립트가 더욱 강력해집니다. 이렇게 하지 않으면 bash(다른 쉘과 마찬가지로)는 변수 대체 결과에 와일드카드를 수행합니다. 이것이 문제의 원인일 수 있습니다.변수 대체 및 명령 대체는 항상 큰따옴표로 묶습니다 "$foo"."$(foo)"결과에 대해 토큰화 및 와일드카드를 수행하려는 경우가 아니라면 말이죠. 또한 큰따옴표가 누락된 스크립트는 단일 공백 ​​대신 공백 시퀀스와 같은 특정 파일 이름에서 작동하지 않습니다.

또한 파일 이름이 손상될 위험을 줄이기 위해 셸 내에서 텍스트 교체를 수행하는 것이 좋습니다.

SUFFIX="(AutoFlac)"
for entry in *"$SUFFIX"*; do
  target=${entry/ $SUFFIX/}
  mv -- "$entry" "$target"
done

대소문자를 구분하지 않는 와일드카드 일치를 강제할 수 있는 방법은 없지만 자체 일치를 수행하여 스크립트에서 대소문자를 무시하도록 할 수 있습니다.

SUFFIX="(autoflac)"
for entry in *; do
  if [[ ${entry,,} = *$SUFFIX* ]]; then
    # Remove everything from the last space to the last .
    mv -- "$entry" "${entry% *}.${entry##*.}"
  fi
done

답변2

쉘이 glob 패턴과 일치하는 파일을 찾을 수 없으면 glob 패턴을 그대로 유지하면서 루프를 실행합니다. 이 동작으로 인해 *(AutoFLAC)*가 항목입니다.

관련 정보