인코딩이 잘못된 파일을 대량으로 바꾸거나 인코딩 된 문자를 대량으로 바꾸는 방법은 무엇입니까?


15

데비안 서버가 있고 인터넷 라디오 방송국을위한 음악을 호스팅하고 있습니다. 예를 들어 많은 파일에 잘못된 인코딩이있어 파일 이름과 경로에 문제가 있습니다.

./music/Bändname - Some Title - additional Info/B�ndname - 07 - This Title Is Cörtain, The EncÃding Not.mp3

이상적으로는 문자 A-Z/ a-z숫자 0-9또는 대시 -/ 밑줄 이 아닌 모든 것을 제거하고 싶습니다 _... 결과는 다음과 같습니다.

./music/Bndname-SomeTitle-additionalInfo/Bndname-07-ThisTitleIsCrtain,TheEncdingNot.mp3

많은 파일과 디렉토리를 위해 이것을 달성하는 방법은 무엇입니까?

이 비슷한 질문을 보았습니다 : 특수 문자가있는 파일 이름 바꾸기 (또는 올바르게 표시)

그러나 이것은 인코딩 만 수정하므로 위에서 설명한 것처럼보다 엄격한 접근 방식을 선호합니다.

답변:


14

파일 디렉토리의 이름을 동시에 바꾸려면 일부 문제가 발생합니다 . 파일 이름 만 바꾸면 충분합니다. 그러나 디렉토리의 이름도 바꾸고 싶습니다. 당신은 할 수 단순히 mv Motörhead/Encöding Motorhead/Encoding때문에 Motorhead호출의 시간에 존재하지 않습니다.

따라서 모든 파일과 폴더를 우선적으로 탐색 한 다음 현재 파일이나 폴더의 이름 만 바꿉니다. 다음은 findOS X에서 GNU 및 Bash 4.2.42에서 작동합니다.

#!/usr/bin/env bash
find "$1" -depth -print0 | while IFS= read -r -d '' file; do
  d="$( dirname "$file" )"
  f="$( basename "$file" )"
  new="${f//[^a-zA-Z0-9\/\._\-]/}"
  if [ "$f" != "$new" ]      # if equal, name is already clean, so leave alone
  then
    if [ -e "$d/$new" ]
    then
      echo "Notice: \"$new\" and \"$f\" both exist in "$d":"
      ls -ld "$d/$new" "$d/$f"
    else
      echo mv "$file" "$d/$new"      # remove "echo" to actually rename things
    fi
  fi
done

new="${f//[\\\/\:\*\?\"<>|]/}"Windows가 처리 할 수없는 항목을 바꾸 려면를 사용하여 정규식을 변경할 수 있습니다.

이 스크립트를로 저장 rename.sh하고로 실행 가능하게 만드십시오 chmod +x rename.sh. 그런 다음처럼 호출하십시오 rename.sh /some/path.

파일 이름 충돌 (“ Notice”알림) 을 해결하십시오 .

당신이 절대적으로 확신 한다면 는 바로 교체하지의 제거 echo그냥 무엇을 인쇄하는 대신 실제로 이름 바꾸기 것에 스크립트에서.

안전을 위해 작은 파일 하위 집합에서 먼저 테스트하는 것이 좋습니다.


옵션 설명

여기에 무슨 일이 있는지 설명하려면 :

  • -depth디렉토리가 깊이 우선으로 재 확보되도록하여 모든 것을 "롤업"할 수 있습니다. 일반적으로 find다르게 순회합니다 (단 , 너비 우선은 아님).
  • -print0보장하는 find출력은 우리가 그것을 읽을 수 있도록, 널 (null)로 구분이다 read -d ''file 가변. 이렇게하면 공백이있는 파일과 줄 바꿈을 포함하여 모든 종류의 이상한 파일 이름을 처리하는 데 도움이됩니다.
  • 우리는 파일의 디렉토리를 얻을 것이다 dirname . 항상 변수를 올바르게 인용하는 것을 잊지 마십시오. 그렇지 않으면 공백이나 글러브 문자가있는 경로가이 스크립트를 손상시킵니다.
  • 로 실제 파일 이름 (또는 디렉토리 이름)을 얻습니다 basename.
  • 그런 다음 $fBash의 문자열 교체 기능 을 사용하여 유효하지 않은 문자를 제거합니다 . 유효하지 않음은 소문자 또는 대문자, 숫자, 슬래시 ( \/), 점 ( \.), 밑줄 또는 빼기 하이픈이 아닌 것을 의미합니다.
  • $f이미 깨끗한 경우 (정리 된 이름이 현재 이름과 동일) 건너 뜁니다.
  • 경우 $new이미 디렉토리에 존재하는 $d(예를 들어, 당신이라는 이름의 파일이 resumerésumé같은 디렉토리에) 경고를 실행합니다. 일부 시스템에서는 이름을 바꾸고 싶지 않습니다.mv foo foo 문제가 발생 . 그렇지 않으면,
  • 마지막으로 원래 파일 (또는 디렉토리)의 이름을 새 이름으로 바꿉니다.

이 때문에 단지 이름 변경, 깊은 계층에 역할을 할 Motörhead/EncödingMotorhead/Encoding두 단계로 이루어집니다 :

  1. mv Motörhead/Encöding Motörhead/Encoding
  2. mv Motörhead Motorhead

이렇게하면 모든 교체가 올바른 순서로 수행됩니다.


예제 파일 및 테스트 실행

기본 폴더의 일부 파일을 다음과 같이 가정합니다 test.

test
test/Motörhead
test/Motörhead/anöther_file.mp3
test/Motörhead/Encöding
test/Randöm
test/Täst
test/Täst/Töst
test/with space
test/with-hyphen.txt
test/work
test/work/resume
test/work/résumé
test/work/schedule

다음은 디버그 모드에서 실행 ( ) echo앞에 실행 된 결과 mv, 즉 호출 될 명령 및 충돌 경고입니다.

mv test/Motörhead/anöther_file.mp3 test/Motörhead/another_file.mp3
mv test/Motörhead/Encöding test/Motörhead/Encoding
mv test/Motörhead test/Motorhead
mv test/Randöm test/Random
mv test/Täst/Töst test/Täst/Tost
mv test/Täst test/Tast
mv test/with space test/withspace
Notice: "resume" and "résumé" both exist in test/work:
-rw-r—r--  …  …  test/work/resume
-rw-r—r--  …  …  test/work/résumé

에 대한 메시지의 부재를 주목하라 with-hyphen.txt, schedule그리고 test그 자체.


1
mv이미 존재 하는 대상이있는 경우를 처리하기 위해 논리를 추가 할 수 있습니다. (1) 이미 깨끗한 mv foo foo파일이있는 경우 (), (2) 이름이 같은 파일이있는 경우 특수 문자 (예 :에 파일 mv Encöding Encoding이 이미있는 경우 ) EncodingEncöding
Scott

좋은 생각이야, 고마워 이 경우 어떻게해야하는지에 대한 구체적인 제안이 있습니까? 당연하다 – 깨끗하고 제정신으로 이것을 달성하는 것은 처음에 보이는 것보다 어렵다. 무언가가 있다면, 자유롭게 편집하십시오.
slhck

충돌을 자동으로 처리하는 것에 대해 생각하는 것이 타당하지 않다고 생각합니다. – 사용자에게 충돌을 식별하여 처리하도록합니다. 제안한대로 답변을 편집했습니다.
Scott

"Encöding"Too much fön! :-)과 함께 예제를 사용하는 +1
Marcel

3 년이 지난 지금도 여기로 돌아옵니다. 너무 유용합니다! :-)
Afr

15

정확히 원하는 것이 아니라는 것을 알고 있지만 원래 인코딩을 알고 있다면 convmv인코딩을 UTF-8로 변경하여 대부분의 문제를 해결할 수 있습니다.

이것은 유효하지 않은 인코딩 된 폴란드 파일 이름이있는 폴더에서 나를 위해 일했습니다.

convmv -f cp1250 -t utf8 -r .

이 명령은 실제로 이름을 바꾸지 않습니다. --notest파일 이름을 바꾸려면 옵션을 추가 하십시오.


1
정적 세트를 가지고 있거나 다양한 문자 세트가없는 사람들에게는 convmv옵션이 놀랍도록 간단하고 완벽합니다. OP의 경우, 잠재적으로 많은 문자 세트를 가지고 있기 때문에 다른 답변과 병합 될 수 있습니다. 왜냐하면 convmv언제 또는 올바른 형식을 찾지 못하는지를 알고있는 것 같습니다. via를 통해 문자셋을 반복함으로써 convmv --list그것들을 올바르게 인코딩 할 수 있습니다.

1
이것은 OP로서 데비안 서버를 운영한다면 요즘 UTF8을 가정 할 것이며,이 경우 원래 문자를 유지할 수 있습니다. 나는 북유럽 문자의 폴더를 가지고 있었고 다음을 사용했다. convmv -t utf8 --nfc -f iso-8859-1 --notest -r .--nfcOS X보다 앞서 리눅스를 따르기 위해 입력하는 것만으로 convmv(유용한) 옵션을 포기한다.

0

이름 바꾸기에 대해 물었습니다.

그러나 MusicBrainz Picard 와 같은 소프트웨어를 사용하면 문제를 쉽게 피할 수 있습니다 .

음악을 식별하고 (오디오 핑거 프린팅) 거대한 MusicBrainz 데이터베이스 에서 필요한 모든 데이터 (표지 이미지 포함)를 다운로드하고 컬렉션을 원하는 패턴에 맞출 수 있도록 파일을 이동할 수 있습니다. 나는 수년간 그것을 사용하고 있으며 항상 Cyrilic에서 Arabic에 이르기까지 완벽하게 작동했습니다. 물론 (적어도 라틴어 기반 스크립트의 경우) ASCII로 변환 할 수도 있습니다.

이 방법을 사용하면 파일을 읽고 완벽하게 사용할 수 있다면 컬렉션의 지저분하고 이름이 불분명 한 것이 실제로 중요하지 않습니다.

(내가 무료라고 언급 했습니까? 자유 언론에서나 무료 맥주 에서처럼? 소프트웨어와 데이터베이스 모두 ..?

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.