отождествите файлы с неASCII или непечатаемыми символами в имени файла

Можно также запустить chrooted Linux, например, Debian или openSUSE.

24
28.01.2018, 04:27
4 ответа

Предположение, которое "внешний" означает "не символ ASCII", затем можно использовать find с шаблоном для нахождения всех файлов, не имеющих печатаемые символы ASCII на их имена:

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

(Пространство является первым печатаемым символом, перечисленным на http://www.asciitable.com/, ~ является последним.)

Подсказка для LC_ALL=C требуется (на самом деле, LC_CTYPE=C и LC_COLLATE=C), иначе диапазон символов интерпретируется неправильно. См. также страницу руководства glob(7). С тех пор LC_ALL=C причины find для интерпретации строк как ASCII это распечатает многобайтовые символы (такой как π) как вопросительные знаки. Для фиксации этого передайте по каналу к некоторой программе (например. 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
./π
34
27.01.2020, 19:41
  • 1
    Знайте, что у Вас есть имена файлов, которые используют внешние наборы символов, которые являются несовместимыми с UTF-8 или ASCII. В тех случаях можно видеть вопросительные знаки вместо символов. –  Lekensteyn 17.01.2014, 13:23
  • 2
    +1, но я использовал бы LC_ALL=C вместо LC_COLLATE=C поскольку это, не имеет большого смысла устанавливать LC_COLLATE на C без установки LC_CTYPE и удостоверяться это все еще работает, даже когда переменная LC_ALL находится в среде. –  Stéphane Chazelas 17.01.2014, 13:47
  • 3
    Если SPC является печатаемым, затем что относительно TAB и LF которые также обычно находятся в текстовых файлах? –  Stéphane Chazelas 17.01.2014, 13:56
  • 4
    Спасибо - это нашло шесть файлов, которые имели длинный дефис, короткий дефис и вариант одинарной кавычки. Они все произошли из MS Word. Никакое различие в файлах, перечисленных между LC_ALL и LC_COLLATE. LC_COLLATE отобразил символы неASCII правильно тогда как отображенный LC_ALL??? вместо этого. Превосходный ответ! –  suspectus 17.01.2014, 14:35
  • 5
    @suspectus я обновил ответом на основе предложений от Stephane. Для LC_COLLATE и LC_CTYPE, см. также find(1) страница справочника. –  Lekensteyn 17.01.2014, 14:44

Если Вы переводите каждое использование имени файла tr -d '[\200-\377]' и сравните его с настоящим именем, затем любые имена файлов, которые имеют специальные символы, не будут тем же.

(Вышеупомянутое предположение, что Вы имеете в виду неASCII с внешним),

6
27.01.2020, 19:41
  • 1
    Это также удаляет [ и ] в большинстве tr реализации. –  Stéphane Chazelas 17.01.2014, 13:21
  • 2
    Да - это действительно удаляло [ и ] в моей системе. –  suspectus 17.01.2014, 13:57
  • 3
    +1 - решение действительно находило весь эти (шесть) имена файлов с не символы ASCII (в дополнение к [ и ]s).спасибо. –  suspectus 17.01.2014, 14:26

Можно использовать 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
3
27.01.2020, 19:41
  • 1
    , который является хорошим расширением моего ответа, но это слишком просто, имена файлов, может иметь новые строки в них, и затем Ваш сценарий не будет работать –  Timo 17.01.2014, 13:16
  • 2
    Если Вы хотите выполнить последующую обработку find вывод, используйте NUL-завершенный вывод/вход как показано в этом ответе. –  Lekensteyn 17.01.2014, 13:20

Принятый ответ полезен, но если ваши имена файлов уже находятся в кодировке, указанной в LANG/LC_CTYPE, лучше просто сделать:

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

На классы символов влияет LC_CTYPE, но приведенная выше команда не использует классы символов, а использует только диапазоны, поэтому LC_CTYPEпросто предотвращает замену необычных символов вопросительными знаками.

1
27.01.2020, 19:41

Теги

Похожие вопросы