6

Я хочу использовать команду оболочки Unix, чтобы найти все файлы в кодировке UTF-16 (содержащие метку порядка байтов UTF-16 (BOM)) в дереве каталогов. Есть ли команда, которую я могу использовать?

5 ответов5

8

Хотя вы просили найти спецификацию, использование file может даже дать вам результаты, если такой спецификации нет. Из man file:

Если файл не соответствует ни одной из записей в магическом файле, он проверяется, чтобы увидеть, является ли он текстовым файлом. Наборы символов ASCII, ISO-8859-x, 8-разрядные расширенные ASCII, отличные от ISO (например, используемые в системах Macintosh и IBM PC), кодировка UTF-8 в кодировке Unicode, кодировка UTF-16 в кодировке Unicode и EBCDIC могут отличаться различными диапазонами и последовательностями байтов, которые составляют печатный текст в каждом наборе. Если файл проходит какой-либо из этих тестов, сообщается его набор символов.

Отсюда, например:

find . -type f -exec file --mime {} \; | grep "charset=utf-16"
1

Вы можете использовать grep:

 grep -rl $(echo -ne '^\0376\0377') *

(Протестировано с помощью bash и GNU grep, может работать с другими.)

Объяснение:

Часть $(echo ... генерирует спецификацию (Hex FE FF, как восьмеричные escape-последовательности), затем она передается grep качестве шаблона, с добавлением '^' (= совпадение начала строки).

-r - рекурсивный поиск, -l заставляет grep печатать имена найденных файлов (вместо соответствующей строки).

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

Кроме того, вы можете попробовать file (в сочетании с find+xargs). file идентифицирует UTF-16 (как «символьные данные UTF-16 Unicode»). Однако я не знаю, насколько это надежно (поскольку использует эвристику).

1

Если у вас есть, вы можете использовать enca:

enca -L none * 2>/dev/null | grep  -i "Universal character"
1

Вот скрипт, который я использую, чтобы найти файлы UTF-16 и затем преобразовать их в UTF-8. #!/ Бен / ш

find ./ -type f |
while read file; do
    if [ "`head -c 2 -- "$file"`" == $'\xff\xfe' ]
    then
        echo "Problems with: $file"
        # If you want to convert to UTF-8 uncomment these lines.
        #cat "$file" | iconv -f UTF-16 -t UTF-8 > "$file.tmp"
        #mv -f "$file.tmp" "$file"
    fi
done
0

Спасибо всем за помощь. На моем Mac лучше всего работали:

find . -type f -exec awk -F '\n' '/^\xFE\xFF|\xFF\xFE/ { print FILENAME; nextfile } { nextfile }' {} \;

Он основан на решении sleske, но учитывает, что метка порядка байтов может быть изменена. Он также использует awk для прекращения поиска спецификации после первой строки, так как спецификация должна находиться в начале файла. Экранирование \x, используемое для указания спецификации, работает с bash, я не знаю, работает ли она с другими оболочками.

Инструмент enca, предложенный ghostdog74, также сделает эту работу, но его не было на моем Mac.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .