파일 이름에 ASCII가 아니거나 인쇄 할 수없는 문자가있는 파일을 식별하십시오.


24

약 70 만 개의 파일이있는 디렉토리 크기 80GB의 경우 파일 이름에 영어 이외의 문자가 포함 된 일부 파일 이름이 있습니다. 파일 목록을 트롤링하는 것 외에는 다음과 같은 것이 있습니다.

  • 이러한 파일 이름을 나열하거나 식별하는 쉬운 방법은 무엇입니까?
  • 인쇄 가능한 영어 이외의 문자를 생성하는 방법-인쇄 가능한 범위에 나열되지 않은 문자 man ascii(이러한 파일이 식별되는지 테스트 할 수 있음)?

답변:


32

"외국"이 "ASCII 문자가 아님"을 의미한다고 가정하면 find패턴과 함께 사용 하여 이름에 인쇄 가능한 ASCII 문자가없는 모든 파일을 찾을 수 있습니다.

LC_ALL=C find . -name '*[! -~]*'

(공간은에 나열된 첫 번째 인쇄 가능한 문자 http://www.asciitable.com/은 , ~마지막입니다.)

에 대한 힌트 LC_ALL=C가 필요합니다 (실제로 LC_CTYPE=CLC_COLLATE=C). 그렇지 않으면 문자 범위가 잘못 해석됩니다. 매뉴얼 페이지도 참조하십시오 glob(7). 때문에 LC_ALL=C원인은 findASCII와 같은 문자열을 해석하기 위해서는 (예 : 멀티 바이트 문자를 인쇄 할 π물음표로). 이 문제를 해결하려면 일부 프로그램 (예 :)으로 파이프 cat하거나 파일로 리디렉션하십시오.

문자 범위를 지정하는 대신 [:print:]"인쇄 가능한 문자"를 선택하는 데 사용할 수도 있습니다. C 로케일을 설정해야합니다.

예:

$ touch $(printf '\u03c0') "$(printf 'x\ty')"
$ ls -F
dir/  foo  foo.c  xrestop-0.4/  xrestop-0.4.tar.gz  π
$ find -name '*[! -~]*'       # this is broken (LC_COLLATE=en_US.UTF-8)
./x?y
./dir
./π
... (a lot more)
./foo.c
$ LC_ALL=C find . -name '*[! -~]*'
./x?y
./??
$ LC_ALL=C find . -name '*[! -~]*' | cat
./x y
./π
$ LC_ALL=C find . -name '*[![:print:]]*' | cat
./x y
./π

1
UTF-8 또는 ASCII와 호환되지 않는 외부 문자 세트를 사용하는 파일 이름이 있습니다. 이러한 경우 문자 대신 물음표가 표시 될 수 있습니다.
Lekensteyn

1
+1이지만 LC_COLLATE를 설정하지 않고 C로 설정 하고 LC_ALL 변수가 환경에 있어도 여전히 작동하는지 확인하는 것이별로 의미가 없으므로 LC_ALL=C대신에 사용하고 싶습니다 . LC_COLLATE=CLC_CTYPE
Stéphane Chazelas

경우 SPC입니다 인쇄 , 다음 대해 TABLF도 일반적으로 텍스트 파일에서 발견되는?
Stéphane Chazelas

1
고마워-긴 하이픈, 짧은 하이픈 및 작은 따옴표의 변형이있는 6 개의 파일이 발견되었습니다. 이들은 모두 MS Word에서 시작되었습니다. LC_ALL과 LC_COLLATE 사이에 나열된 파일에는 차이가 없습니다. LC_COLLATE는 비 ASCII 문자를 올바르게 표시했지만 LC_ALL은 표시 했습니까 ??? 대신에. 훌륭한 답변!
suspectus

1
@suspectus 나는 Stephane의 제안에 따라 답변으로 업데이트했습니다. 들어 LC_COLLATELC_CTYPE, 또한 참조 find(1)맨 페이지를.
Lekensteyn

6

각 파일 이름을 사용하여 번역 tr -d '[\200-\377]'하고 원래 이름과 비교하면 특수 문자가있는 파일 이름은 동일하지 않습니다.

(외국인과 비 ASCII를 의미한다고 가정 한 위의 내용)


2
그것도 제거 [하고 ]대부분 tr의 구현.
Stéphane Chazelas

예 - 그것은 제거했다 []내 시스템에.
suspectus

+1-솔루션이 ASCII 기호가 아닌 ( []s 이외에) 모든 (6) 파일 이름을 찾았습니다 . 감사.
suspectus

3

당신이 사용할 수있는 tr파일 이름에서 외국 문자를 삭제하고 외국 문자를 포함하고 있는지 확인하기 위해 원본 파일 이름으로 결과를 비교합니다.

find . -type f > filenames
while read filename; do
      stripped="$(printf '%s\n' "$filename" | tr -d -C '[[:alnum:]][[:space:]][[:punct:]]')"
      test "$filename" = "$stripped" || printf '%s\n' "$filename"; 
done < filenames

4
그게 내 대답에 좋은 확장이지만, 너무 간단하고, 파일 이름은 그들에 줄 바꿈을 가질 수 있습니다 다음 스크립트를하지 않습니다 일
티모

1
find출력 을 후 처리 하려면 이 답변에 표시된대로 NUL 종료 출력 / 입력을 사용 하십시오 .
Lekensteyn

0

허용되는 답변 은 도움이되지만 파일 이름이 이미 LANG/에 지정된 인코딩으로되어 있으면 다음과 같이하는 LC_CTYPE것이 좋습니다.

LC_COLLATE=C find . -name '*[! -~]*'

문자 클래스는의 영향을 LC_CTYPE받지만, 위 명령은 문자 클래스를 사용하지 않고 범위 만 사용하므로 LC_CTYPE이상한 문자가 물음표로 바뀌지 않도록합니다.

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