入力ファイルを変換された出力でiconvに置き換えるにはどうすればよいですか?


70

ディレクトリ内のすべての* .phpファイルを列挙して適用するbashスクリプトがありますiconv。これは、STDOUTに出力を取得します。

-o(私の経験では)パラメーターを追加すると、おそらく変換が行われる前に空のファイルが実際に書き込まれるので、変換を行うようにスクリプトを調整し、入力ファイルを上書きするにはどうすればよいですか?

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

「>」に関する警告も参照してください。
G-マン

回答:


76

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ユーティリティJoey Hessのmoreutilsに含まれています)は、これを自動化します。

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

この答えはiconv、すべてのフィルタープログラムだけに適用されるわけではありません。いくつかの特別なケースに言及する価値があります。

  • GNU sedとPerlに-pは、-iファイルを所定の場所に置き換えるオプションがあります。
  • あなたのファイルが非常に大きい場合、あなたのフィルタは変更または削除いくつかの部分が物事を追加することはありません(たとえばさgreptrsed 's/long input text/shorter text/')、あなたは危険な生活のように、あなたが本当にしたいことな場所にファイルを変更する(ここで言及した他のソリューションの作成新しい出力ファイルを作成し、最後に所定の場所に移動するため、何らかの理由でコマンドが中断された場合、元のデータは変更されません)。

3
の著者がspongeJoey Hessのみに帰属するべきかどうかはよくわかりません。彼が保持しmoreutilsているパッケージが含まれspongeていますが、の起源に関して、spongeのホームページからリンクをたどることによりmoreutils、最初に掲載され、 Colin Watsonによる組み込み提案されていることがわかりました。 Unixの哲学に適合します。私が書いたそのようなものの中で私のお気に入りはsponge"(Mon、06 Feb 2006)です。
imz-イヴァンザカリヤシェフ

3
Mac OSを使用していますが、iconvに-oオプションはありません。`iconv -f cp1251 -t utf8 -o "$ file.new" "$ file" `に変更する必要がありますiconv -f cp1251 -t utf8 "$file" > "$file.new"
code4j

などの一部のコマンドは、パラメーターsortに関して非常に賢く-o、出力ファイルが入力と同じであると検出した場合、一時ファイルを内部的に管理するため、動作します。
-jesjimher

56

別の方法はrecode、いくつかの変換にlibiconvライブラリを使用します。その動作は、入力ファイルを出力に置き換えることです。したがって、これは機能します。

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

recodeパラメータとして複数の入力ファイルを受け入れ、あなたは余裕ができforたループを:

recode cp1251..utf8 *.php

2
おかげで、これはより多くの賛成に値する。エンコーディング間の2点について、マニュアルに見つめている場合だけ不思議...
neurino

2
「REQUESTはしばしばBEFORE..AFTERのように見えます。BEFOREとAFTERは文字セットです。」このマニュアルは、これらのすべての二重ドット(構文の一部)と三重ドット(これを意味します)を追うのは難しいです。アドバイス:info recode代わりに試してください。もっと冗長です。
マナトワーク

4

今のところ

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

魅力のように働く


5
最初は、実際に機能すると思っていました。しかし、32Kを超える出力は切断され、さらに入力するとコアダンプがトリガーされるようです。
x-yuri 14

1

ExモードでVimを使用できます。

ex -sc '%!iconv -f cp1251 -t utf8' -cx "$file"
  1. % すべての行を選択

  2. ! コマンドを実行する

  3. x 保存して閉じます


0

以下に簡単な例を示します。開始するのに十分な情報が得られるはずです。

#!/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
echo "`iconv -f cp1251 -t utf8 $file`" > "$file"

私のために働く


0

findを使用できますが、少なくともこれはRaspbian Stretchで私のために働いた:

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

0

1つのオプションは、インプレース編集用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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.