5

Я поздно попытался найти ответ на вопрос, похожий на мой, по stackoverflow (Найти имена файлов не-UTF8 в файловой системе Linux), чтобы получить дальнейшие ответы, но пока безуспешно, так что здесь снова ...

У меня та же проблема, что и у OP по ссылке выше, и convmv - отличный инструмент для исправления собственной файловой системы. Поэтому мой вопрос академический, но я нахожу неудовлетворительным (на самом деле я не могу поверить), что «find» не может найти нестандартные символы ascii.

Есть ли кто-нибудь, кто знал бы, какую комбинацию опций использовать, чтобы найти имена файлов, которые содержат нестандартные символы на том, что похоже на Unicode FS, в моем случае символы кажутся расширенными ascii на 8 бит, а не unicode, файлы приходят Windows-машина (iso-8859-1), и мне регулярно нужно их получать. Я хотел бы увидеть, как find и / или grep могут делать то же самое, что и convmv.

Примеры файлов:

> ls
Abc�def ÉÈéèáà-rest everest éverest

> ls -b
Abc\251def  ÉÈéèáà-rest  everest  éverest

Первый файл поступает из Windows (или имитируется touch $(printf "Abc\xA9def")).

> find . -regex '.*[^a-zA-Z./].*'
./ÉÈéèáà-rest

> ls | egrep '[^a-zA-Z]'
ÉÈéèáà-rest

Отсутствует почти все из них (дефис, сохраняющий этот файл, можно увидеть с помощью цветного grep). Все, что здесь происходит, - это не то, что я ожидал: ни find, ни grep не в состоянии воспринимать акцентированное письмо как выходящее за пределы диапазона, предусмотренного [^ a-zA-Z./].

> find . -regex '.*é.*'
./éverest
./ÉÈéèáà-rest

> ls | egrep 'é'
ÉÈéèáà-rest
éverest

> ls | egrep '[é]'
ÉÈéèáà-rest
éverest

> find . -regex '.*[é].*'
./éverest
./ÉÈéèáà-rest

Причудливо оба способны подобрать стандартный акцент при наличии (в том числе в диапазоне). Любая попытка найти или grep с \xA9, \0251 или \o251 не удалась (нет совпадения).

> ls | fgrep e
Abc�def
ÉÈéèáà-rest
everest
éverest

Поиск не спорных символов показывает все файлы с grep, как я и ожидал.

> find . -regex '.*e.*'
./éverest
./ÉÈéèáà-rest
./everest

> find . -name '*e*'
./éverest
./ÉÈéèáà-rest
./everest

однако поиск очень дискриминационный: даже при поиске нормального символа мне кажется, что он удаляет имена файлов, которые содержат символы, выходящие за пределы допустимого диапазона для схемы кодирования имен файловой системы.

Что касается меня, если файл находится в файловой системе, то find должен найти его, верно? Но, может быть, есть особенность, о которой я не знаю?

Любые идеи будут очень цениться.

3 ответа3

8

Инструменты GNU, кажется, имеют код, который заставляет акцентированные буквы обрабатываться как их базовые буквы при сопоставлении с классом символов регулярного выражения, если поддерживается кодировкой символов. Эта функция предназначена для того, чтобы упростить написание регулярных выражений, но в данном случае это мешает вам.

Попробуйте следующую модификацию вашей командной строки "find":

LANG=C find . -regex '.*[^a-zA-Z./].*'

Это устанавливает переменную среды LANG только в контексте команды "find". Поскольку кодировка языка "C" поддерживает только ASCII, акцентированные буквы больше не будут обрабатываться как их базовые буквы, и поэтому ваше регулярное выражение будет правильно соответствовать.

5

Ответ Джандера отлично справляется со своей задачей, для тех, кто заинтересован в том, чтобы извлечь из этого больше пользы, вот еще один совет.

Если LANG = C, найдите символы, отличные от ascii, с вопросительными знаками. Чтобы преобразовать это обратно в их обычное отображение с этой файловой системой, просто передайте вывод в cat.

LANG=C find . -regex '.*[^a-zA-Z./-].*'
./??verest
./????????????-rest
./Abc?def

LANG=C find . -regex '.*[^a-zA-Z./-].*' | cat
./éverest
./ÉÈéèáà-rest
./Abc�def
0
find . | grep -E '.*[^[:print:]].*'

Список всех классов символов posix см. По адресу :http://www.regular-expressions.info/posixbrackets.html.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .