Элегантный способ поиска файлов UTF-8 с помощью спецификации?

94

В целях отладки мне нужно рекурсивно искать в каталоге все файлы, которые начинаются с отметки порядка байтов (BOM) UTF-8. Мое текущее решение - это простой сценарий оболочки:

find -type f |
while read file
do
    if [ "`head -c 3 -- "$file"`" == $'\xef\xbb\xbf' ]
    then
        echo "found BOM in: $file"
    fi
done

Или, если вы предпочитаете короткие, нечитаемые однострочные строки:

find -type f|while read file;do [ "`head -c3 -- "$file"`" == $'\xef\xbb\xbf' ] && echo "found BOM in: $file";done

Это не работает с именами файлов, которые содержат разрыв строки, но таких файлов в любом случае ожидать не следует.

Есть ли более короткое или элегантное решение?

Есть ли какие-нибудь интересные текстовые редакторы или макросы для текстовых редакторов?

Vog
источник

Ответы:

166

Как насчет этой простой команды, которая не просто находит, но очищает неприятную спецификацию? :)

find . -type f -exec sed '1s/^\xEF\xBB\xBF//' -i {} \;

Люблю "находить" :)

Предупреждение. Приведенное выше приведет к изменению двоичных файлов, содержащих эти три символа.

Если вы хотите просто показать файлы спецификации, используйте этот:

grep -rl $'\xEF\xBB\xBF' .
Денис
источник
9
Неправильно определяет PDF с помощью маркера спецификации .. это потому, что он ищет весь документ, а не только первую строку
Оливье Рефало
1
Или с помощью ack: "ack '\ xEF \ xBB \ xBF'"
Smar
5
измените команду sed, добавив 1 перед ведущей 's', чтобы она
применялась
27
Используется grep -rlI $'\xEF\xBB\xBF' .для игнорирования двоичных файлов.
dbernard 05
1
Обнаруживает и изменяет JPG и другие двоичные файлы, как уже было сказано.
Jehy
41

Лучший и самый простой способ сделать это в Windows:

Total Commander → перейдите в корневой каталог проекта → найдите файлы ( Alt+ F7) → типы файлов *. * → Найдите текст «EF BB BF» → установите флажок «Hex» → поиск

И вы получите список :)

Ян Пшибило
источник
4
Приятно, особенно использование моего давнего любимого Total Commander, но, к сожалению, он страдает той же проблемой, что и многие другие: он ищет все байты в файле, сообщается так много изображений и т. Это можно немного улучшить, используя RegEx вместо Hex и выполняя поиск по запросу «^ \ xEF \ xBB \ xBF», который удалит многие изображения, но все еще содержит файлы с спецификацией на полпути (хотя их должно быть немного) и, конечно, любые двоичные файлы, которые имеют код символа новой строки ascii непосредственно перед спецификацией. Тем не менее, все изображения пропали в моем тестовом поиске.
Леголас
13
find . -type f -print0 | xargs -0r awk '
    /^\xEF\xBB\xBF/ {print FILENAME}
    {nextfile}'

Большинство приведенных выше решений проверяют не только первую строку файла, даже если некоторые (например, решение Маркуса) затем фильтруют результаты. Это решение проверяет только первую строку каждого файла, поэтому оно должно быть немного быстрее.

Арон Гриффис
источник
1
Got работает со следующим на Linux (RHEL6) -find . -type f -print0 | xargs -0 awk '/^\xEF\xBB\xBF/ {print FILENAME} {nextfile}'
Оливье Рефало
Как мне изменить ваш код, чтобы исправить эти файлы после их обнаружения?
Блэк
7

Если вы принимаете некоторые ложные срабатывания (в случае, если есть нетекстовые файлы или, что маловероятно, в середине файла есть ZWNBSP), вы можете использовать grep:

fgrep -rl `echo -ne '\xef\xbb\xbf'` .
CesarB
источник
5

Я бы использовал что-то вроде:

grep -orHbm1 "^`echo -ne '\xef\xbb\xbf'`" . | sed '/:0:/!d;s/:0:.*//'

Это гарантирует, что спецификация будет начинаться с первого байта файла.

Маркус Грип
источник
5

Вы можете использовать их grepдля поиска и Perl для их удаления следующим образом:

grep -rl $'\xEF\xBB\xBF' . | xargs perl -i -pe 's{\xEF\xBB\xBF}{}'
теория
источник
Этот сработал для меня, принятый ответ - нет (я на Mac)
mjsarfatti
4

Для пользователя Windows см. Это (хороший сценарий PHP для поиска BOMв вашем проекте).

жульен
источник
На связанном веб-сайте отображается: «Веб-сайт не в сети, кешированная версия недоступна».
vog
тот же скрипт также доступен в github: github.com/emrahgunduz/BomCleaner
emrahgunduz
Спасибо, дружище, твой ответ спас мне день.
Крунал Панчал
И BOM Finder: github.com/svn2github/wikia/blob/master/extensions/FCKeditor/… (на случай, если кому-то не нравится «автоматическая» очистка, или он просто хочет найти файлы с BOM)
meloniq
3

Излишним решением для этого является phptags(не viинструмент с таким же именем), который специально ищет сценарии PHP:

phptags --warn ./

Будет выводиться что-то вроде:

./invalid.php: TRAILING whitespace ("?>\n")
./invalid.php: UTF-8 BOM alone ("\xEF\xBB\xBF")

И --whitespaceрежим автоматически исправит такие проблемы (рекурсивно, но утверждает, что он только переписывает скрипты .php.)

Марио
источник
2
find -type f -print0 | xargs -0 grep -l `printf '^\xef\xbb\xbf'` | sed 's/^/found BOM in: /'
  • find -print0 помещает нуль \ 0 между каждым именем файла вместо использования новых строк
  • xargs -0 ожидает аргументы, разделенные нулем, вместо разделенных строк
  • grep -l перечисляет файлы, соответствующие регулярному выражению
  • Регулярное выражение ^\xeff\xbb\xbfне совсем корректно, поскольку оно будет соответствовать файлам UTF-8 без спецификации, если в начале строки у них есть пробелы нулевой ширины.
Джонатан Райт
источник
Вам все еще нужна "голова 1" в трубе перед grep
MSalters
2

Я использовал это для исправления только файлов JavaScript:

find . -iname *.js -type f -exec sed 's/^\xEF\xBB\xBF//' -i.bak {} \; -exec rm {}.bak \;
Refineo
источник
0

Если вы ищете файлы UTF, команда file работает. Он сообщит вам, какова кодировка файла. Если там есть какие-либо символы, отличные от ASCII, он будет предлагать UTF.

file *.php | grep UTF

Однако это не будет работать рекурсивно. Вы, вероятно, можете настроить какую-нибудь причудливую команду, чтобы сделать ее рекурсивной, но я просто искал каждый уровень индивидуально, как показано ниже, пока у меня не закончились уровни.

file */*.php | grep UTF
Майк Доттерер
источник