Стандартный Unix утилита , как grep
и diff
использовать некоторые эвристики для классификации файлов как «текст» или «двоичный». (Например grep
, вывод может включать строки вроде Binary file frobozz matches
.)
Есть ли удобный тест, который можно применить в zsh
сценарии для выполнения аналогичной «текстовой / двоичной» классификации? (Кроме чего-то вроде grep '' somefile | grep -q Binary
.)
(Я понимаю, что любой такой тест обязательно будет эвристическим и, следовательно, несовершенным.)
file
это стандартная утилита, которая может использовать магию файлов для определения типов файлов в меру своих возможностей. Он может распознавать большинство текстовых форматов и довольно неплохо справляется с двоичными форматами. Если все, что вы пытаетесь сделать, это выяснить, является ли файл текстовым или нет, это команда, которая вас интересует.file
будут напечатаны, напримерshell script
, для некоторых файлов, которые я хотел бы классифицировать как «текст». Есть ли способ получитьfile
просто напечататьtext
илиbinary
?cut
команд.file
вывод данных в трубопроводcut
- это решение - конечно, есть пропущенное место, которое приводит к сбою и большинство людей там обращаются к Y вместо X, но комментарии и ответ Стефана показывают правильный способ определить, является ли файл текстовым или нет.Ответы:
Если вы запрашиваете
file
только MIME-тип, вы получите много разных, таких какtext/x-shellscript
иapplication/x-executable
т. Д., Но я думаю, что если вы просто проверите «текстовую» часть, вы должны получить хорошие результаты. Например (-b
без имени файла в выводе):источник
file
, что вы можете пропустить некоторые текстовые форматы:application/xml
(и аналогично , как RSS)application/ecmascript
,application/json
,image/svg+xml
, ... Вы должны были бы белый список тех.application/*
типы не предназначены для потребления человеком, даже если они могут быть основаны на тексте для облегчения разработки и отладки. Вот почему есть и atext/xml
и anapplication/xml
. Поэтому вопрос о том, следует ли рассматривать их как текст, зависит от потребностей ФП.cut -d/ -f1
Другой подход заключается в использовании
isutf8
из коллекции moreutils .Он завершается с 0, если файл является допустимым UTF-8 или ASCII, или с короткими замыканиями, печатает сообщение об ошибке (тишина с
-q
) и завершается с 1 в противном случае.источник
Если вам нравится эвристика, используемая GNU
grep
, вы можете использовать ее:Он ищет байты NUL в первом буфере, считанном из файла (несколько килобайт для обычного файла, но может быть намного меньше для канала или сокета или некоторых других устройств
/dev/random
). В локалях UTF-8 он также помечает байтовые последовательности, которые не образуют допустимых символов UTF-8. Предполагается, чтоLC_ALL
не установлен на что-то, где язык не является английским.${1-$REPLY}
Форма позволяет использовать его в качествеzsh
Глоб классификатора:перечислил бы двоичные файлы.
источник
Вы можете попытаться определить,
iconv
можете ли вы прочитать файл. Это менее эффективно, чемfile
(который просто читает пару байтов с начала), но даст вам более надежные результаты:Это в
iconv
основном делает невозможным, но если он сталкивается с недопустимыми данными (недопустимый UTF-8 в этом примере), он прекратит работу и завершит работу.источник
-f
и-t
вместо GNU сделает его более переносимым. Обратите внимание, что он будет называть «двоичные» файлы, которые он не может открыть. Это будет называть пустые файлы «текст».iconv
. Но-f
и-t
обычно лучше.Вы можете написать скрипт, который вызывает
file
, и использовать оператор case для проверки интересующих вас случаев.Например
хотя, конечно, может быть много особых случаев, которые представляют интерес. Просто проверяя
strings
копиюlibmagic
, я вижу около 200 случаев, например,Некоторые используют строку «текст» как часть другого типа, например,
Точно так же
script
может быть частью слова, но я не вижу проблем в этом случае. Но скрипт должен проверять"text"
как слово , а не подстроку .Напоминаем, что в
file
выводе не используется точное описание, которое всегда содержит «скрипт» или «текст». Особые случаи - это то, что нужно учитывать. Продолжение прокомментировало, что--mime-type
работает, пока этот подход не будет, для.svg
файлов. Тем не менее, в тесте я вижу эти результаты для SVG-файлов:который я выбрал, увидев тысячу файлов, показывающих только 6 с текстом в выводе mime-типа. Возможно, сопоставление «xml» в конце вывода mime-типа может быть более полезным, скажем, чем сопоставление «SVG», но использование сценария для выполнения этого возвращает вас к предложению, сделанному здесь.
Вывод
file
требует некоторой настройки в любом сценарии и не является на 100% надежным (его смущают несколько моих сценариев Perl, называющих их «данные»).Существует более одной реализации
file
. Наиболее часто используемая выполняет свою работуlibmagic
, которую можно использовать из разных программ (возможно, не напрямуюzsh
, хотяpython
можно).Согласно таблице сравнения тестов файлов для оболочки, Perl, Ruby и Python , в Perl есть
-T
опция, которую он может использовать для предоставления этой информации. Но это не перечисляет сопоставимую функцию дляzsh
.Дальнейшее чтение:
источник
file
, вывод GNU для файлов SVG:SVG Scalable Vector Graphics image
не содержит слова text. Я думал, что этот подход будет лучше, чем принятый ответ проверки типа mime, но он все еще пропускает некоторые типы.image/svg+xml
. На самом деле - только что проверил 1000-файл то же самое, только 6 вышли как «текст» в соответствии только с MIME-тип. Я буду придерживаться сценария, который, по крайней мере, можно заставить работать по мере необходимости.file
имеет опцию,--mime-encoding
которая пытается определить кодировку файла.Вы можете использовать,
file --mime-encoding | grep binary
чтобы определить, является ли файл двоичным файлом. Он работает надежно, хотя может быть запутан одним недопустимым символом в длинном текстовом файле.Например, я псевдоним
cat
следующего сценария оболочки, чтобы избежать разрушения моего терминала, случайно открыв двоичный файл:источник
Категории являются произвольными. Прежде чем ответить, как сделать классификацию, нужно (строгое) определение. Чтобы иметь определение, вам нужна цель .
Итак, что вы хотите сделать с этой классификацией?
источник
сделаю это. Смотрите документацию для
-B
и-T
(ищите на этой странице строкуThe -T and -B switches work as follows
).источник
perl -le 'print -B $ARGV[0] ? "binary" : "text"' --
может быть понятнее Или дажеperl -le 'print -B $_ ? "binary" : "text", @ARGV > 1 ? "\t$_" : "" for @ARGV' --
Я внес вклад в https://github.com/audreyr/binaryornot. У него нет оболочки для командной строки (пока), но это простая библиотека Python, которую достаточно просто вызвать даже из CLI. Он использует довольно эффективную эвристику, чтобы определить, является ли файл текстовым или двоичным.
источник
Мне сейчас этот ответ немного староват, но я думаю, что мой друг научил меня хорошему «взлому» сделать это.
Вы используете
diff
команду и сверяете свой файл с тестовым текстовым файлом:$ diff filetocheck testfile.txt
Теперь, если
filetocheck
это бинарный файл, вывод будет:Binary files filetocheck and testfile.txt differ
Таким образом, вы можете использовать
diff
команду и, например, написать функцию, которая выполняет проверку в скрипте.источник