it-roy-ru.com

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

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

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

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

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

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

83
vog

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

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

Я люблю "найти" :)

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

,.

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

grep -rl $'\xEF\xBB\xBF' .
152
Denis

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

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

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

39
Jan Przybylo
find . -type f -print0 | xargs -0r awk '
    /^\xEF\xBB\xBF/ {print FILENAME}
    {nextfile}'

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

12
Aron Griffis

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

fgrep -rl `echo -ne '\xef\xbb\xbf'` .
7
CesarB

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

grep -rl $'\xEF\xBB\xBF' . | xargs Perl -i -pe 's{\xEF\xBB\xBF}{}'
5
theory

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

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

Который будет гарантировать, что BOM происходит, начиная с первого байта файла.

5
Marcus Griep

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

4
julien

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

phptags --warn ./

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

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

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

3
mario

Я использовал это, чтобы исправить только файлы JavaScript:

find . -iname *.js -type f -exec sed 's/^\xEF\xBB\xBF//' -i.bak {} \; -exec rm {}.bak \;
2
Refineo
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 не совсем корректно, так как оно будет соответствовать не-BOMed файлам UTF-8, если они имеют пробелы нулевой ширины в начале строки
2
Jonathan Wright

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

file *.php | grep UTF

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

file */*.php | grep UTF
0
Mike Dotterer