Я хочу использовать команду оболочки Unix, чтобы найти все файлы в кодировке UTF-16 (содержащие метку порядка байтов UTF-16 (BOM)) в дереве каталогов. Есть ли команда, которую я могу использовать?
5 ответов
Хотя вы просили найти спецификацию, использование 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"
Вы можете использовать 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»). Однако я не знаю, насколько это надежно (поскольку использует эвристику).
Если у вас есть, вы можете использовать enca
:
enca -L none * 2>/dev/null | grep -i "Universal character"
Вот скрипт, который я использую, чтобы найти файлы 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
Спасибо всем за помощь. На моем Mac лучше всего работали:
find . -type f -exec awk -F '\n' '/^\xFE\xFF|\xFF\xFE/ { print FILENAME; nextfile } { nextfile }' {} \;
Он основан на решении sleske, но учитывает, что метка порядка байтов может быть изменена. Он также использует awk для прекращения поиска спецификации после первой строки, так как спецификация должна находиться в начале файла. Экранирование \x, используемое для указания спецификации, работает с bash, я не знаю, работает ли она с другими оболочками.
Инструмент enca, предложенный ghostdog74, также сделает эту работу, но его не было на моем Mac.