Да так же, как и делали, только в отдельном каталоге с копиями файлов, чтобы не зацепить ничего лишнего.
Навеяло.

Уже третий час сидит программист в ванной и читает этикетку на флаконе: намылить голову, смыть шампунь, повторить...
Как мне теперь правильно решить проблему изменения win-1251 в utf-8 в нескольких папках?
Если имена файлов - то один подход.
Если содержимое файлов, как я понял, то быстро это вот так:
1) Посмотреть, чтобы не поломать файлы ненуждающиеся в обработке, какие файлы будут обработаны
find /каталог/с/файлами/для/обработки -type f -name "*htm*"
Выбор файлов определяется параметрами. Здесь будут выбраны htm и html и прочие .htm*
Регистр играет роль.
2) И обработать файлы
find /каталог/с/файлами/для/обработки -type f -name "*htm*" | while read fileName ; do iconv -f WINDOWS-1251 -t UTF-8 "${fileName}" --output "tmpFile" && mv "tmpFile" "${fileName}" ; done && [ -e "tmpFile" ] && rm "tmpFile"
Разбор этой строки:
Найти файлы:
find /каталог/с/файлами/для/обработки -type f -name "*htm*"
Отправить список найденных на вход следующей команде:
|
Считывать в переменную fileName по одному имени со входа (точка с запятой разделяет разные команды):
while read fileName ; do
Конвертировать файлы:
iconv -f WINDOWS-1251 -t UTF-8 "${fileName}" --output "tmpFile"
Переместить, если предыдущая команда вернула код "успех":
&& mv "tmpFile" "${fileName}"
Кончились имена и закончилось чтение в цикле:
; done
Если цикл вернул "успех", проверить не остался ли временный файл:
&& [ -e "tmpFile" ]
Если проверка вернула "успех", удалить временный файл:
&& rm "tmpFile"
Я использую скрипт
convert-cp1251-utf8.sh#!/bin/bash
# Begin functions declarations
# Функция выбирает имена файлов и выводит имена "на стандартный выход".
function selectFiles {
# Здесь определено какие файлы внутри рабочего каталога обрабатывать. См. справку по команде find - http://www.opennet.ru/man.shtml?topic=find&category=1&russian=2
find "${workingDir}" -type f -name "${templateFileName}"
}
# Функция конвертирует файлы.
function convertFiles {
while read fileName
do
if iconv -f WINDOWS-1251 -t UTF-8 "${fileName}" --output "${tempFileName}" # Конвертация файла
then
# Если конвертация была успешна, то заменить оригинал файла на конвертированный и записать имя в журнал если замена удалась без ошибок).
mv --force "${tempFileName}" "${fileName}" && echo "${fileName}" >> "${logFileName}"
rm -f "${tempFileName}" # Удалить временный файл.
else
# Если конвертация не удалась, то прекратить работу.
echo "Error: failed to convert \"${fileName}\". Log file name is \"${logFileName}\"."
exit 1 # Перывание скрипта с кодом выхода 1.
fi
done <<< "$( selectFiles )" # Запуск "подачи" имён файлов на "вход цикла".
}
function showMan {
echo "Use options --show or --do-job supplemented with --template=\"*.*\" --target-dir=\"/tmp\"."
echo "Enclose directory name and file name template with double qoutes, as \"/tmp\"."
}
# End functions declarations
# Start job processing
# Здесь начинаются первые активные действия в скрипте, фактически "начало" скрипта тут. А выше только подготовка и объявления-описания нужных объектов.
# Разбор параметров командной строки. Черновик.
# TODO: While [ -n "${1}" ] ; do echo "Arg value is ${1#*=}."; shift 1; done
routineLaunchName=""
while [ -n "${1}" ] ; do
case "${1%%=*}" in
--target-dir)
workingDir="${1#*=}"
if [ ! -d "${workingDir}" ]
then
echo "Not exist directory \"${workingDir}\"."
exit 1
fi
;;
--template) # Шаблон, по которому выбирать имена.
templateFileName="${1#*=}"
;;
--show) # Если в командной строке указать эту опцию, то - только покажет выбранные имена файлов.
routineLaunchName="selectFiles"
;;
--do-job) # Если в командной строке указать эту опцию, то - конвертирует файлы.
rm -f "${tempFileName}" # Очистка перед началом.
echo -n > "${logFileName}" # Создание файла журнала.
routineLaunchName="convertFiles"
;;
--help|-h)
showMan
exit 0 # Перывание скрипта с кодом выхода 0.
;;
*)
echo "Unknown option \"${1}\" in command line."
showMan
exit 1
;;
esac
shift 1
done
if [ -z "${routineLaunchName}" ] # Если не выбрано действие.
then
showMan
exit 1
fi
if [ -z "${templateFileName}" ] # Если шаблон имени файла не определился.
then
echo "Name template to be processed is not specified."
showMan
exit 1
fi
if [ -z "${workingDir}" ] # Если не определён рабочий каталог.
then
echo "Target directory to be processed is not specified."
showMan
exit 1
fi
logFileName="${workingDir}/convert-log-$( date '+%Y-%m-%d_%H%M_%S%N' ).log" # Файл журнала.
tempFileName="${tmp-iconv-file}" # Временный файл.
"${routineLaunchName}" # Запуск выбранной функции.
Сохраняете его на диск.
Для просмотра, чтобы не поломать файлы ненуждающиеся в обработке, какие файлы он затронет запускаете:
bash convert-cp1251-utf8.sh --show --template="*htm*" --target-dir="/каталог/с/файлами/для/обработки"
Если файлы в текущем каталоге и ниже, то можно вот так:
bash convert-cp1251-utf8.sh --show --template="*htm*" --target-dir="$(pwd)"
Если показанный список файлов годится, то реально запускаете конвертацию:
bash convert-cp1251-utf8.sh --do-job --template="*htm*" -target-dir="/каталог/с/файлами/для/обработки"
Чтобы поменять фильтр имён, нужно в скрипте менять параметры команды find. В т.ч. добавление "-maxdepth 1 -mindepth 1" ограничит поиск только одним единственным каталогом, без захода в подкаталоги.
Если при конвертации были ошибки, нужно сначала посмотреть в файл журнала предыдущего раза. Посмотреть на вывод в терминале - с чем ошибка, имя файла... Скрипт нельзя, не разобравшись, запускать второй раз.
Не разбирался, что будет если уже конвертированное в UTF8 ещё раз обработать.
И конечно: не уверена - работай над копией.