web-dev-qa-db-ja.com

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

ディレクトリ内のすべての* .phpファイルを列挙してiconvを適用するbashスクリプトがあります。これは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がない場合は、シェルリダイレクトを使用して同じ効果を得ることができます。

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/')。本当にしたい場合があります ファイルをインプレースで変更 (ここで説明する他の解決策は、新しい出力ファイルを作成し、最後にそれを移動するため、何らかの理由でコマンドが中断された場合、元のデータは変更されません)。

別の方法は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. !コマンドを実行

  3. x保存して閉じる

1
Steven Penny

1つのオプションは、Perliconvへのインターフェイスとその-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

これが 簡単な例 です。それはあなたが始めるのに十分な情報を与えるはずです。

#!/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