it-swarm-ru.tech

Как я могу сделать так, чтобы iconv заменил входной файл на преобразованный вывод?

У меня есть скрипт bash, который перечисляет все файлы * .php в каталоге и применяет к нему iconv. Это получает вывод в STDOUT.

С добавлением -o Параметр (по моему опыту) на самом деле записывает пустой файл, вероятно, до того, как произойдет преобразование, как я могу настроить свой сценарий так, чтобы он выполнял преобразование, а затем перезаписывал входной файл?

for file in *.php
do
    iconv -f cp1251 -t utf8 "$file"
done
73
meder omuraliev

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

Создайте новый временный файл для вывода, затем переместите его на место.

for file in *.php
do
    iconv -f cp1251 -t utf8 -o "$file.new" "$file" &&
    mv -f "$file.new" "$file"
done

Если у вашей платформы iconv нет -o, вы можете использовать перенаправление Shell для того же эффекта.

for file in *.php
do
    iconv -f cp1251 -t utf8 "$file" >"$file.new" &&
    mv -f "$file.new" "$file"
done

утилита Колина Уотсона sponge (включена в moreutils Джои Хесса ) автоматизирует это:

for file in *.php
do
    iconv -f cp1251 -t utf8 "$file" | sponge "$file"
done

Этот ответ применим не только к iconv, но и к любой программе фильтрации. Стоит упомянуть несколько особых случаев:

  • GNU sed и Perl -p есть -i возможность заменить файлы на месте.
  • Если ваш файл очень большой, ваш фильтр только изменяет или удаляет некоторые части, но никогда не добавляет что-либо (например, grep, tr, sed 's/long input text/shorter text/') и вам нравится жить опасно, вы, возможно, захотите по-настоящему изменить файл на месте (другие решения, упомянутые здесь, создают новый выходной файл и перемещают его на место в конце, так что оригинал данные не изменяются, если команда прерывается по какой-либо причине).
80
Gilles 'SO- stop being evil'

Альтернативой является recode, которая использует библиотеку libiconv для некоторых преобразований. Его поведение заключается в замене входного файла с выходным, так что это будет работать:

for file in *.php
do
    recode cp1251..utf8 "$file"
done

Поскольку recode принимает несколько входных файлов в качестве параметра, вы можете сэкономить цикл for:

recode cp1251..utf8 *.php
61
manatwork

Теперь

find . -name '*.php' -exec iconv -f CP1251 -t UTF-8 {} -o {} \;

работает как шарм

4
galeksandrp

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

ex -sc '%!iconv -f cp1251 -t utf8' -cx "$file"
  1. % выбрать все строки

  2. ! Команда Run

  3. x сохранить и закрыть

1
Steven Penny

Один из вариантов - использовать интерфейс Perl для iconv и ​​его -i режим для редактирования на месте:

Perl -MText::Iconv -i -pe '
  BEGIN{$i=Text::Iconv->new(qw(cp1252 UTF-8));$i->raise_error(1)}
  $_ = $i->convert($_)' ./*.php

С GNU awk, вы также можете сделать что-то вроде:

gawk -v cmd='iconv -f cp1252 -t utf-8' -i inplace '
  {print | cmd}; ENDFILE {close(cmd)}' ./*.php

ksh93 Shell также имеет >; оператор для того, что сохраняет выходные данные во временном файле, который переименовывается в перенаправленный файл, если команда была успешной:

for f in *.php; do
  iconv -f cp1252 -t utf-8 < $f >; $f
done
0
Stéphane Chazelas

Вот простой пример . Это должно дать вам достаточно информации, чтобы начать.

#!/bin/bash
#conversor.sh
#Author.....: dede.exe
#E-mail.....: [email protected]
#Description: Convert all files to a another format
#             It's not a safe way to do it...
#             Just a desperate script to save my life...
#             Use it such a last resort...

to_format="utf8"
file_pattern="*.Java"

files=`find . -name "${file_pattern}"`

echo "==================== CONVERTING ===================="

#Try convert all files in the structure
for file_name in ${files}
do
        #Get file format
        file_format=`file $file_name --mime-encoding | cut -d":" -f2 | sed -e 's/ //g'`

        if [ $file_format != $to_format ]; then

                file_tmp="${unit_file}.tmp"

                #Rename the file to a temporary file
                mv $file_name $file_tmp

                #Create a new file with a new format.
                iconv -f $file_format -t $to_format $file_tmp > $file_name

                #Remove the temporary file
                rm $file_tmp

                echo "File Name...: $file_name"
                echo "From Format.: $file_format"
                echo "To Format...: $to_format"
                echo "---------------------------------------------------"

        fi
done;
0
dede.exe
echo "`iconv -f cp1251 -t utf8 $file`" > "$file"

работает для меня

0
CoNsTaR

Вы можете использовать find, по крайней мере, это сработало для меня на Raspbian Stretch:

find . -type f -name '*php' -execdir iconv -f cp1251 -t UTF-8 '{}' -o '{}'.tmp \; -execdir mv '{}'.tmp '{}' \;
0
rannala