Пакетное преобразование файлов latin-1 в utf-8 с помощью iconv
У меня есть этот один PHP-проект на моем OSX, который находится в latin1 -encoding. Теперь мне нужно преобразовать файлы в UTF8. Я не очень похож на кодер, и я попробовал что-то, что я нашел из Интернета:
mkdir new
for a in `ls -R *`; do iconv -f iso-8859-1 -t utf-8 <"$a" >new/"$a" ; done
Но это не создает структуру каталогов, и это приносит мне огромную нагрузку на ошибки при запуске. Может ли кто-нибудь придумать опрятное решение?
Ответы
Ответ 1
Нельзя использовать ls
, и цикл for
тоже не подходит. Кроме того, целевой каталог должен находиться за пределами исходного каталога.
mkdir /path/to/destination
find . -type f -exec iconv -f iso-8859-1 -t utf-8 "{}" -o /path/to/destination/"{}" \;
Нет необходимости в цикле. Параметр -type f
включает файлы и исключает каталоги.
Edit:
Версия OS X iconv
не имеет опции -o
. Попробуйте следующее:
find . -type f -exec bash -c 'iconv -f iso-8859-1 -t utf-8 "{}" > /path/to/destination/"{}"' \;
Ответ 2
Некоторые хорошие ответы, но я нашел это намного проще в моем случае с вложенным каталогом сотен файлов для конвертирования:
ПРЕДУПРЕЖДЕНИЕ. Это приведет к записи файлов на место, поэтому сделайте резервную копию
$ vim $(find . -type f)
# in vim, go into command mode (:)
:set nomore
:bufdo set fileencoding=utf8 | w
Ответ 3
Чтобы преобразовать полное дерево каталогов рекурсивно из iso-8859-1 в utf-8, включая создание подкаталогов, ни одно из коротких решений выше не работало для меня, потому что структура каталогов не была создана в целевой. На основании ответа Денниса Уильямсона я придумал следующее решение:
find . -type f -exec bash -c 't="/tmp/dest"; mkdir -p "$t/`dirname {}`"; iconv -f iso-8859-1 -t utf-8 "{}" > "$t/{}"' \;
Он создаст клон текущего поддерева каталога в /tmp/dest
(приспосабливается к вашим потребностям), включая все подкаталоги и все файлы iso-8859-1
, преобразованные в utf-8
. Протестировано на macosx.
Btw: проверьте кодировки файлов с помощью
file -I file.php
чтобы получить информацию о кодировании.
Надеюсь, что это поможет.
Ответ 4
Я создаю следующий script, который (i) создает резервные копии всех файлов tex в каталоге "преобразован", (ii) проверяет кодировку каждого tex файла и (iii) преобразует в UTF-8 только файлы tex в ISO-8859-1.
FILES=*.tex
for f in $FILES
do
filename="${f%.*}"
echo -n "$f"
#file -I $f
if file -I $f | grep -wq "iso-8859-1"
then
mkdir -p converted
cp $f ./converted
iconv -f ISO-8859-1 -t UTF-8 $f > "${filename}_utf8.tex"
mv "${filename}_utf8.tex" $f
echo ": CONVERTED TO UTF-8."
else
echo ": UTF-8 ALREADY."
fi
done
Ответ 5
Если все файлы, которые вы должны преобразовать, являются .php, вы можете использовать следующее, которое по умолчанию рекурсивно:
for a in $(find . -name "*.php"); do iconv -f iso-8859-1 -t utf-8 <"$a" >new/"$a" ; done
Я считаю, что ваши ошибки были связаны с тем, что ls -R
также производит вывод, который не может быть распознан iconv как допустимое имя файла, что-то вроде ./my/dir/structure:
Ответ 6
Это преобразует все файлы с расширением имени файла .php
- в текущий каталог и его подкаталоги - сохраняя структуру каталогов:
find . -name "*.php" -exec sh -c "iconv -f ISO-8859-1 -t UTF-8 {} > {}.utf8" \; -exec mv "{}".utf8 "{}" \;
Примечания:
Чтобы получить список файлов, которые будут нацелены заранее, просто запустите команду без флагов -exec
(find . -name "*.php"
для примера)
Использование sh
, как это, позволяет использовать трубопровод и перенаправление с помощью -exec, что необходимо, потому что не все версии iconv поддерживают флаг -o
.
Добавление .utf8
в имя файла вывода, а затем удаление его может показаться странным, но это необходимо. Использование одного и того же имени для выходных и входных файлов может вызвать проблемы:
-
Для больших файлов (около 30 Кбайт в моем опыте) он вызывает дамп ядра (или termination by signal 7
)
-
Некоторые версии iconv, похоже, создают выходной файл перед чтением входного файла, а это означает, что если входные и выходные файлы имеют одинаковое имя, входной файл перезаписывается пустым файлом, прежде чем он будет читать.
Ответ 7
Используйте mkdir -p "${a%/*}";
до значка.
Обратите внимание, что вы используете потенциально опасную конструкцию for
, когда в именах файлов есть пробелы, см. http://porkmail.org/era/unix/award.html.
Ответ 8
find . -iname "*.php" | xargs -I {} echo "iconv -f ISO-8859-1 -t UTF-8 \"{}\" > \"{}-utf8.php\""
Ответ 9
Используя ответы Денниса Уильямсона и Альберто Заккагни, я придумал следующий script, который преобразует все файлы указанного типа файла из всех подкаталогов. Затем вывод будет собран в одной папке, заданной /path/to/destination
mkdir /path/to/destination
for a in $(find . -name "*.php");
do
filename=$(basename $a);
echo $filename
iconv -f iso-8859-1 -t utf-8 <"$a" >"/path/to/destination/$filename";
done
Базисное имя функции возвращает имя файла без пути к файлу.
Альтернативный (интерактивный пользователь):
Теперь я также создал пользовательский интерактивный script, который позволяет вам решить, хотите ли вы перезаписать старые файлы или просто переименовать их. Дополнительная благодарность за помощь
for a in $(find . -name "*.tex");
do
iconv -f iso-8859-1 -t utf-8 <"$a" >"$a".utf8 ;
done
echo "Should the original files be replaced (Y/N)?"
read replace
if [ "$replace" == "Y" ]; then
echo "Original files have been replaced."
for a in $(find . -name "*.tex.utf8");
do
file_no_suffix=$(basename -s .tex.utf8 "$a");
directory=$(dirname "$a");
mv "$a" "$directory"/"$file_no_suffix".tex;
done
else
echo "Original files have been converted and converted files were saved with suffix '.utf8'"
fi
Получайте удовольствие от этого, и я был бы благодарен за любые комментарии, чтобы улучшить его, спасибо!
Ответ 10
Все в порядке с приведенными выше ответами, но если это "смешанный" проект, то есть уже есть файлы UTF8, тогда мы можем столкнуться с проблемами, поэтому здесь мое решение, я сначала проверяю кодировку файлов.
#!/bin/bash
# file name: to_utf8
# current encoding:
encoding=$(file -i "$1" | sed "s/.*charset=\(.*\)$/\1/")
if [ "${encoding}" = "iso-8859-1" ] || [ "${encoding}" = "iso-8859-2" ];
then
echo "recoding from ${encoding} to UTF-8 file : $1"
recode ISO-8859-2..UTF-8 "$1"
fi
#example:
#find . -name "*.php" -exec to_utf8 {} \;
Ответ 11
На unix.stackexchange.com был задан аналогичный вопрос, и пользовательский manatwork предложил перекодировать, который делает трюк очень красиво.
Я использовал его для преобразования ucs-2 в utf-8 на месте
recode ucs-2..utf-8 *.txt