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

Вы могли передать его по каналу через strings первый:-

cat file.pdf | strings | grep <...etc...>
72
13.04.2011, 01:08
7 ответов

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

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

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

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

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

Colin Watson sponge утилита (включенный в moreutils Joey Hess) автоматизирует это:

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

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

  • GNU sed и Perl -p имейте a -i опция заменить файлы на месте.
  • Если Ваш файл является чрезвычайно большим, Ваш фильтр только изменяет или удаляет некоторые части, но никогда не добавляет вещи (например. grep, tr, sed 's/long input text/shorter text/'), и Вам нравится жить опасно, можно хотеть действительно изменить файл на месте (другие решения, упомянутые здесь, создают новый выходной файл и перемещают его в место в конце, таким образом, исходные данные неизменны, если команда прервана по какой-либо причине).
78
27.01.2020, 19:31
  • 1
    я не совсем уверен ли авторство sponge должен быть приписан исключительно Joey Hess; это - пакет moreutils это включает sponge то, что он поддерживает, но в отношении источника sponge, переходя по ссылкам от домашней страницы moreutils, Я нашел, что это первоначально отправило и предложенный для включения Colin Watson: "Joey пишет об отсутствии новых инструментов, которые вписываются в философию Unix. Мой фаворит таких вещей, которые я записал, sponge"(Понедельник, 06 февраля 2006). –  imz -- Ivan Zakharyaschev 30.03.2011, 17:13
  • 2
    я использую Mac OS, нет никакой-o опции в iconv, я должен изменить '"$file.new" "$file" iconv-f cp1251-t utf8-o' на iconv -f cp1251 -t utf8 "$file" > "$file.new" –  code4j 06.09.2014, 23:17
  • 3
    Некоторые команды, как sort, довольно умное касающееся -o параметр, и если они обнаруживают выходной файл, совпадает с, вводит, они внутренне управляют временным файлом, таким образом, он просто работает. –  jesjimher 18.04.2018, 15:55

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

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

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

recode cp1251..utf8 *.php
60
27.01.2020, 19:31
  • 1
    Спасибо, это заслуживает большего количества upvotes. Просто удивление, где смотрится в руководстве о 2 точках между кодировкой... –  neurino 20.11.2012, 23:14
  • 2
    “ ЗАПРОС часто похож ПРЕЖДЕ.. ПОСЛЕ, с ПРЕЖДЕ и будучи наборами символов”. Тому руководству действительно трудно следовать со всеми теми двойными точками (которые являются частью синтаксиса), и тройные точки (которые означают больше из этого). Совет: попробовать info recode вместо этого. Является более подробным. –  manatwork 21.11.2012, 08:46

В настоящее время

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

работает как очарование

4
27.01.2020, 19:31

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

#!/bin/bash
#conversor.sh
#Author.....: dede.exe
#E-mail.....: dede.exe@gmail.com
#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
27.01.2020, 19:31

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

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

  2. ! запустить команду

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

1
27.01.2020, 19:31
echo "`iconv -f cp1251 -t utf8 $file`" > "$file"

у меня работает

0
27.01.2020, 19:31

Один из вариантов — использовать интерфейс 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также имеет оператор >;для сохранения вывода во временном файле, который переименовывается в перенаправленный файл, если команда выполнена успешно:

for f in *.php; do
  iconv -f cp1252 -t utf-8 < $f >; $f
done
0
27.01.2020, 19:31

Теги

Похожие вопросы