파일 이름이 UTF-8인 파일 시스템에 파일 이름 오류가 있습니다. zsh: , Latin 1 D�sinstaller
에 따른 실제 이름은 "제거"를 의미하는 야만적인 프랑스어입니다. Zsh는 이를 일치시키지 않지만 와일드카드와 일치시킬 것입니다. 이는 제가 예상하는 동작입니다.D$'\351'sinstaller
Désinstaller
[[ $file =~ '^.*$' ]]
*
이제 나는 여전히 런타임에 그것을 찾을 것으로 기대합니다 find . -name '*'
. 사실, 파일 이름이 이 테스트에 실패할 것이라고는 결코 예상하지 않습니다. 그러나 의 경우 LANG=en_US.utf8
파일은아니요LANG=C
이 나타나면 (또는 en_US
, 또는 ) 을 설정해야 ''
작동합니다.
질문: 그 뒤에 구현은 무엇입니까? 결과를 어떻게 예측하나요?
정보: Arch Linux 3.14.37-1-lts, find(GNU findutils) 4.4.2
답변1
정말 좋은 보너스네요. GNU find 의 소스 코드를 잠깐 살펴보면 이는 fnmatch
유효하지 않은 바이트 시퀀스( pred_name_common
in pred.c
)의 동작 방식으로 귀결된다고 말하고 싶습니다.
b = fnmatch (str, base, flags) == 0;
(...)
return b;
이 코드는 fnmatch
반환 값이 0인지 테스트하지만 오류를 확인하지는 않습니다. 이로 인해 오류가 "일치 없음"으로 보고됩니다.
수년 전에는 *
손상된 파일 이름에서도 패턴에 대해 항상 true를 반환하도록 이 libc 함수의 동작을 변경하는 것이 제안되었지만 내가 아는 한 이 아이디어는 거부되었을 것입니다(참조:https://sourceware.org/ml/libc-hacker/2002-11/msg00071.html):
fnmatch가 잘못된 멀티바이트 문자를 감지하면 "*"가 해당 문자열과 일치할 수 있도록 단일 바이트 일치로 대체해야 합니다.
왜 이것이 더 낫거나 더 정확합니까? 기성 방법이 있나요?
Stéphane Chazelas가 주석과 2002년 같은 스레드에서 언급했듯이 이는 유효하지 않은 문자를 차단하지 않는 셸에서 수행하는 glob 확장과 일치하지 않습니다. 아마도 더 혼란스러운 점은 역방향 테스트가 이름이 손상된 파일만 일치시킬 것이라는 점입니다( bash 에서 create file 사용 touch $'D\351marrer' $'Touch\303\251' $'\346\227\245\346\234\254\350\252\236'
).
$ find -name '*'
.
./Touché
./日本語
$ find -not -name '*'
./D?marrer
따라서 귀하의 질문에 답하려면 이 경우의 동작을 이해 fnmatch
하고 함수의 반환 값을 처리하는 방법을 알면 find
이를 예측할 수 있습니다. 아마도 문서를 읽는 것만으로는 답을 찾을 수 없을 것입니다.
답변2
찾다 -name
쉘을 사용하는 옵션패턴 일치 기호일치하는 파일 이름을 수행합니다. *
패턴이다여러 문자 일치, 0개 이상의 문자로 구성된 문자열과 일치해야 합니다.
find
사용성냥패턴 일치를 확인하여 사용할 수 있습니다.길검사 결과:
$ touch $'\U1212'aa
$ touch D$'\351'sinstaller
$ LC_ALL=en_US.utf8 ltrace -e fnmatch find -name '*'
find->fnmatch("foo", "foo", 0) = 0
find->fnmatch("Foo", "foo", 0) = 1
find->fnmatch("Foo", "foo", 16) = 0
find->fnmatch("*", ".", 0) = 0
.
find->fnmatch("*", "D\351sinstaller", 0) = -1
find->fnmatch("*", "\341\210\222aa", 0) = 0
./ሒaa
+++ exited (status 0) +++
일치 실패를 나타내려면 D\351sinstaller
, fnmatch
return 을 사용하십시오 . 이와 같은 유효한 문자와 일치합니다.-1
ሒaa
귀하의 경우 UTF-8
로케일 에 \351
잘못된 문자가 있어 패턴 일치가 실패합니다.