특수 문자가있는 파일의 대량 이름 바꾸기 (또는 올바르게 표시)


20

이 파일과 같이 특수 문자가 포함 된 파일을 포함하는 많은 디렉토리와 하위 디렉토리가 있습니다.

robbie@phil:~$ ls testsktest.txt 
test?sktest.txt

찾기는 이스케이프 시퀀스를 나타냅니다.

robbie@phil:~$ find testsktest.txt -ls 
424512 4000 -rwxr--r-x   1 robbie   robbie    4091743 Jan 26 00:34 test\323sktest.txt

콘솔에서 이름을 입력 할 수있는 유일한 이유는 탭 완성 때문입니다. 이것은 또한 수동으로 이름을 바꾸고 특수 문자를 제거 할 수 있음을 의미합니다.

LC_ALL을 UTF-8로 설정했는데 도움이되지 않는 것 같습니다 (또한 새로운 쉘에는 없음).

robbie@phil:~$ echo $LC_ALL
en_US.UTF-8

Mac에서 ssh를 사용하여 컴퓨터에 연결하고 있습니다. 우분투 설치입니다.

robbie@phil:~$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=7.10
DISTRIB_CODENAME=gutsy
DISTRIB_DESCRIPTION="Ubuntu 7.10"

Shell은 Bash이고 TERM은 xterm-color로 설정되어 있습니다.

이 파일들은 꽤 오랫동안 존재 해 왔으며 Ubuntu 설치를 사용하여 만들지 않았습니다. 그래서 시스템 인코딩 설정이 무엇인지 알 수 없습니다.

나는 다음 라인을 따라 시도했다.

find . -type f -ls | sed 's/[^a-zA-Z0-9]//g'

그러나 원하는 모든 것을 수행하는 솔루션을 찾을 수 없습니다.

  1. 표시 할 수없는 문자가있는 모든 파일을 식별하십시오 (위의 방법은 너무 무시 함)
  2. 디렉토리 트리의 모든 파일에 대해 (반복적으로) mv oldname newname을 실행하십시오.
  3. 선택적으로, ä와 같은 특수 문자를 음역하는 기능 (필수는 아니지만 훌륭 할 것입니다)

또는

  1. 이러한 모든 파일을 올바르게 표시합니다 (파일을 열려고 할 때 응용 프로그램에 오류가 없음)

모든 파일을 반복하고 이동하는 것과 같은 비트와 조각이 있지만 파일을 식별하고 mv 명령에 올바르게 형식을 지정하는 것은 어려운 부분 인 것 같습니다.

왜 올바르게 표시되지 않는지 또는 올바른 인코딩을 "추측"하는 방법에 대한 추가 정보도 환영합니다. (나는 convmv를 시도했지만 내가 원하는 것을 정확하게하지 않는 것 같습니다 : http://j3e.de/linux/convmv/ )


아래의 단일 답변은 첫 번째 방법을 따르고 (새 인코딩으로 찾고 이름을 바꿉니다) 두 번째 방법은 흥미로울 것입니다. 이제 원격 파일 이름에 사용되는 인코딩을 알면 원격 호스트에 ssh하는 방법 파일 이름이 올바르게 표시되고 키보드로 이름을 입력하여 관리 할 수있는 방법은 무엇입니까?
imz-Ivan Zakharyaschev

답변:


21

난 당신이 볼 생각 이름이 유효한 UTF-8이 아닌 바이트 시퀀스가 포함되어 있기 때문에 잘못된 문자. 일반적인 유닉스 파일 시스템 (여러 파일 포함)의 파일 이름은 바이트 문자열이며 사용할 인코딩을 결정하는 것은 응용 프로그램에 달려 있습니다. 요즘에는 UTF-8을 사용하는 경향이 있지만 특히 일반 ASCII로 살 수 없으며 UTF-8이 존재하기 전에 다른 인코딩을 사용하는 로케일에서는 보편적이지 않습니다.

시도 LC_CTYPE=en_US.iso88591 ls파일 이름이 ISO-8859-1 (라틴어-1)에 의미가 있는지. 그렇지 않은 경우 다른 로케일을 시도하십시오. LC_CTYPE로케일 설정 만 중요합니다.

UTF-8 로케일에서 다음 명령은 이름이 UTF-8이 아닌 모든 파일을 표시합니다.

grep-invalid-utf8 () {
  perl -l -ne '/^([\000-\177]|[\300-\337][\200-\277]|[\340-\357][\200-\277]{2}|[\360-\367][\200-\277]{3}|[\370-\373][\200-\277]{4}|[\374-\375][\200-\277]{5})*$/ or print'
}
find | grep-invalid-utf8

recode 또는 iconv를 사용하여 다른 로케일에서 더 적합한 지 확인할 수 있습니다 .

find | grep-invalid-utf8 | recode latin1..utf8
find | grep-invalid-utf8 | iconv -f latin1 -t utf8

많은 파일 이름이 특정 인코딩 (예 : latin1)으로되어 있다고 판단되면 이름을 바꾸는 한 가지 방법은

find | grep-invalid-utf8 |
rename 'BEGIN {binmode STDIN, ":encoding(latin1)"; use Encode;}
        $_=encode("utf8", $_)'

이것은 데비안과 우분투에서 사용 가능한 perl rename 명령을 사용합니다. -n실제로 파일 이름을 바꾸지 않고도 수행 할 작업을 보여주기 위해 전달할 수 있습니다 .


고마워, 오늘 나중에 이것들 몇 가지를 시도 할 것이다! 이 답변이 허용되는 것 같습니다 :)
RobbieV

찾기 | grep '[[: print :]]'명령은 단순히 모든 파일을 반환하는 것 같습니다. UTF-8은 "일반"문자를 사용하는 다른 많은 인코딩과 호환되지 않아야합니까?
RobbieV

@ RobbieV : 나는 오타 grep [^[:print:]]가 인쇄 할 수없는 문자를 검색 하려고 했습니다. 그러나 나는 방금 GNU grep으로 테스트했으며 유효하지 않은 UTF-8 시퀀스는 잡히지 [^[:print:]]않습니다 (인쇄 할 수없는 문자가 아니므로 전혀 문자가 아닙니다). 유효하지 않은 utf8 시퀀스를 사용하여 줄을 더 길게 배치하여 게시물을 편집했습니다. 나는 또한의 방향을 고정했습니다 참고 recodeiconv예.
Gilles 'SO- 악마 그만해'

완벽하게 작동했습니다. iconv 명령을 제외한 모든 명령을 시도했으며 모두 예상대로 작동합니다. 순수한 마법!
RobbieV

제안 된 latin1 인코딩조차 올바른 것입니다 :)
RobbieV

1

나는 이것이 오래된 질문이라는 것을 알고 있지만 비슷한 해결책을 찾기 위해 밤새 검색했습니다. 몇 가지 유용한 팁을 찾았지만 정확히 필요한 것을 수행하지 않았으므로 원하는 결과를 얻으려면 몇 가지를 혼합하고 일치시켜야했습니다.

단순히 특수 문자를 제거하고 (.) 점으로 대체

for f in *.txt; do mv "$f" `echo $f | sed "s/[^a-zA-Z0-9.]/./g"`; done

cronjob에서 사용하려면 매분마다 다음을 수행했습니다.

*/1 * * * * cd /path/to/files/ && for f in *.txt; do mv "$f" `echo $f | sed "s/[^a-zA-Z0-9.]/./g"`; done >/dev/null 2>&1

나는 그것이 내 하루를 보냈을 때 누군가가 도움이되기를 바랍니다. :)


(1) 명확성을 위해, 당신은 변경할 수 있습니다 `…`에 대한이 $(…)- 볼 , , 및 . (2) "$f"타당한 이유가없는 한 항상 쉘 변수 참조 (예 :)를 인용해야하며 자신이하고있는 일을 확실하게 확신해야합니다. 이는에도 적용됩니다 echo "$f" | sed …. 또한 전체 $(…)(또는 `…`) 표현식 에도 적용됩니다 . 즉 mv "$f" "$(echo "$f" | sed "…")". … (계속)
Scott

(계속)… (3)로 시작하는 파일 이름으로부터 보호 하려면을 말해야 합니다. (4)“foo ♥ bar.txt”및“foo ♠ bar.txt”라는 파일이있는 경우 두 파일의 이름을 모두“foo.bar.txt”로 바꾸려고 시도 할 수 있습니다. 파기 될 파일. (5) 지구상에서 1 분에 한 번씩 왜 이렇게 하시겠습니까? mv -- "$f" …-
Scott

파일을 자동 다운로드하는 토렌트 스크립트가 있습니다. 때로는 일부 파일에 업 로더를 버리는 문자가 있습니다. 그래서 특수 문자로 파일 이름을 바꾸면 내 cron이 모든 문제를 해결했으며 업 로더가 원활하게 작업합니다.
Topps70

그래서 (이 fithale tha, t was-down_loaded.ext)는 (this.fi.le.tha.t.was.down.loaded.ext)로 바뀝니다
Topps70

0

이제 원격 끝의 파일 이름에 어떤 인코딩이 사용되는지 알면 (첫 번째 답변의 주석에 따라 "latin1") 두 번째 방법을 수행 할 수 있습니다 -로컬 터미널을 실행하고 ssh 를 그런 식으로 원격 파일 이름 (: 이름을 바꾸 오히려 첫 번째 방법보다) 올바르게 표시됩니다 .

처럼 다음과 같이 특수 인코딩에서 작동하는 터미널을 로컬에서 시작할 수 있습니다.

LC_ALL = en_US.latin1 xvt &

xvt 터미널 프로그램을 나타냅니다.

아마도 내가 생각한 것처럼 기존 로케일은이라고 불리지 en_US.iso88591않을 것 en_US.latin1입니다.


0

이것은 대량 요구 사항을 충족시키지 못하지만 비슷한 이름을 가진 파일의 여러 버전이 하나의 이상한 문자로만 다른 유사한 문제가 발생했습니다. 불행히도 이것은 내가 일반적으로 사용하는 와일드 카드 트릭을 사용하여 범죄자의 이름을 바꿀 수 없음을 의미했습니다.

결국 Filezilla를 사용하여 SFTP 클라이언트로 연결하고 파일을 찾아 GUI를 사용하여 이름을 바꿨습니다. Filezilla는 닷지 캐릭터를 잘 처리했습니다.

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