Как идентифицировать текстовые файлы в unix системах через терминал?

Как идентифицировать текстовые файлы в unix системах через терминал?

13.11.2012 07:32:58 Просмотров 28 Источник

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

Проблема в том, что я не знаю как идентифицировать все текстовые файлы в папке.

У вопроса есть решение - Посмотреть?

https://ru.stackoverflow.com/questions/163448/%d0%9a%d0%b0%d0%ba-%d0%b8%d0%b4%d0%b5%d0%bd%d1%82%d0%b8%d1%84%d0%b8%d1%86%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d1%82%d1%8c-%d1%82%d0%b5%d0%ba%d1%81%d1%82%d0%be%d0%b2%d1%8b%d0%b5-%d1%84%d0%b0%d0%b9%d0%bb%d1%8b-%d0%b2-unix-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0%d1%85-%d1%87%d0%b5%d1%80%d0%b5%d0%b7-%d1%82%d0%b5%d1%80%d0%bc%d0%b8%d0%bd%d0%b0%d0%bb#comment163492_163448
Считайте пробелы,возвраты каретки, табуляцию в каждом файле. Если больше определенного процента от размера, файл текстовый. Эвристика конечно, но быть может подойдет. Большие файлы можно игнорировать. wc и grep в помощь.

Ответы - Как идентифицировать текстовые файлы в unix системах через терминал? / Как идентифицировать текстовые файлы в unix системах через терминал?

Является ответом!
drdaeman

13.11.2012 07:49:38

Я бы предложил вот такое извращение:

find . -maxdepth 1 -type f \
     -exec sh -c "file -bi '{}' | grep -q ^text/ && echo '{}'" \; \
  | xargs wc -l | head -n -1 | sort -gk 1 > line_counts.txt

Что тут творится:

  • find . -maxdepth 1 -type f — ищем в текущем каталоге (не ломясь глубже) все файлы (-type f)
  • -exec sh -c "…" \; — для каждого из них выполняем команду sh -c "…" (вместо «{}» будет подставлено имя файла). Смысл сего действа в том, что просто так мы пайпу в find не засунем, оно не поймет, вот и приходится вызывать шелл.
  • file -bi '{}' — определяем MIME-тип файла (-i), само имя файла не выводим (-q). Это может быть не самый точный вариант определения, см. примечания ниже.
  • grep -q ^text/ — выбираем строчки, которые начинаются с «text/», но ничего не выводим (-q), а только сообщаем кодом выхода, нашлось что-то или нет
  • && echo '{}' — если нашлось, то будет выполнена правая часть && и выведено имя файла.
  • xargs wc -l — все поступающие имена файлов будут поданы аргументами wc, которое и посчитает строки (-l).
  • head -n -1 — обрезаем последнюю строчку, с суммарным результатом
  • sort -gk 1 — численно (-g) сортируем по первому полю (-k 1)

Возможны вариации. В частности, думаю, не одним ^text/ все ограничивается (некоторые файлы, представляющие собой текст в UTF-8 имеют MIME-типы в application/*, но есть и всякие application/octet-stream, которые, вообще говоря, ни разу не текстовые), так что, может быть, лучше подойдет что-то в духе file -b '{}' | grep -Fq ' text'. Так же, если файлов будет очень много, а имена у них длинные — придется вызывать wc не один раз, а по разу для каждого файла, «xargs -I '{}' wc -l '{}'».

Да, я использовал, в основном, GNU'шные утилиты (GNU findutils, GNU coreutils, GNU grep), если не считать BSD'шного file. На не-GNU системах могут оказаться другие утилиты, которые могут какой-нибудь опции и не понять, или понять не так. В общем, YMMV, если что — смотрите в документацию.

Все это, правда, сломается если какой-нибудь любитель странного создаст файл, с именем, содержащим символ перевода строки (\n). Тогда пайпа, начиная с xargs сломается. Чтобы решить, придется добавлять еще && echo -e '\x00' (или как-то так) и добавить xargs аргумент -0 (--null).

https://ru.stackoverflow.com/questions/163448/%d0%9a%d0%b0%d0%ba-%d0%b8%d0%b4%d0%b5%d0%bd%d1%82%d0%b8%d1%84%d0%b8%d1%86%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d1%82%d1%8c-%d1%82%d0%b5%d0%ba%d1%81%d1%82%d0%be%d0%b2%d1%8b%d0%b5-%d1%84%d0%b0%d0%b9%d0%bb%d1%8b-%d0%b2-unix-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0%d1%85-%d1%87%d0%b5%d1%80%d0%b5%d0%b7-%d1%82%d0%b5%d1%80%d0%bc%d0%b8%d0%bd%d0%b0%d0%bb/163456#comment163461_163456
плюс за изврат) тоже когдато так развлекался)))
https://ru.stackoverflow.com/questions/163448/%d0%9a%d0%b0%d0%ba-%d0%b8%d0%b4%d0%b5%d0%bd%d1%82%d0%b8%d1%84%d0%b8%d1%86%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d1%82%d1%8c-%d1%82%d0%b5%d0%ba%d1%81%d1%82%d0%be%d0%b2%d1%8b%d0%b5-%d1%84%d0%b0%d0%b9%d0%bb%d1%8b-%d0%b2-unix-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0%d1%85-%d1%87%d0%b5%d1%80%d0%b5%d0%b7-%d1%82%d0%b5%d1%80%d0%bc%d0%b8%d0%bd%d0%b0%d0%bb/163456#comment163463_163456
Юникс рулит
https://ru.stackoverflow.com/questions/163448/%d0%9a%d0%b0%d0%ba-%d0%b8%d0%b4%d0%b5%d0%bd%d1%82%d0%b8%d1%84%d0%b8%d1%86%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d1%82%d1%8c-%d1%82%d0%b5%d0%ba%d1%81%d1%82%d0%be%d0%b2%d1%8b%d0%b5-%d1%84%d0%b0%d0%b9%d0%bb%d1%8b-%d0%b2-unix-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0%d1%85-%d1%87%d0%b5%d1%80%d0%b5%d0%b7-%d1%82%d0%b5%d1%80%d0%bc%d0%b8%d0%bd%d0%b0%d0%bb/163456#comment163469_163456
Изврат чуть проще, может не очень надежно, но пишется влет wc -l file * | grep text | awk '{ print $1 }' | tr -d : | sort -gk 1
https://ru.stackoverflow.com/questions/163448/%d0%9a%d0%b0%d0%ba-%d0%b8%d0%b4%d0%b5%d0%bd%d1%82%d0%b8%d1%84%d0%b8%d1%86%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d1%82%d1%8c-%d1%82%d0%b5%d0%ba%d1%81%d1%82%d0%be%d0%b2%d1%8b%d0%b5-%d1%84%d0%b0%d0%b9%d0%bb%d1%8b-%d0%b2-unix-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0%d1%85-%d1%87%d0%b5%d1%80%d0%b5%d0%b7-%d1%82%d0%b5%d1%80%d0%bc%d0%b8%d0%bd%d0%b0%d0%bb/163456#comment163479_163456
@avp: Да, но оно сломается на первом же файле, с именем, содержащим пробелы и двоеточия. У меня такой оказался как раз в той директории, где тестировал.
https://ru.stackoverflow.com/questions/163448/%d0%9a%d0%b0%d0%ba-%d0%b8%d0%b4%d0%b5%d0%bd%d1%82%d0%b8%d1%84%d0%b8%d1%86%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d1%82%d1%8c-%d1%82%d0%b5%d0%ba%d1%81%d1%82%d0%be%d0%b2%d1%8b%d0%b5-%d1%84%d0%b0%d0%b9%d0%bb%d1%8b-%d0%b2-unix-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0%d1%85-%d1%87%d0%b5%d1%80%d0%b5%d0%b7-%d1%82%d0%b5%d1%80%d0%bc%d0%b8%d0%bd%d0%b0%d0%bb/163456#comment163498_163456
А что не работает? Ну, там (кроме двоеточий, пробелов и т.п.) еще последнюю строку (total) надо удалять. Я же написал, это просто влет набито. Если реальная задача, то надо подумать, главное определиться, что считать текстовым файлом. Если имена вообще любые, то я бы не мучался, а на Си написал (если тип файла правильно утилита file определяет, то вызывал бы ее через popen).
Закрыть X