Iconvをディレクトリにポイントしようとすると、現在のエンコーディングに関係なく、すべてのファイルがUTF-8に変換されます
私はこのスクリプトを使用していますが、どのエンコーディングから取得するかを指定する必要があります。現在のエンコーディングを自動検出するにはどうすればよいですか?
dir_iconv.sh
#!/bin/bash
ICONVBIN='/usr/bin/iconv' # path to iconv binary
if [ $# -lt 3 ]
then
echo "$0 dir from_charset to_charset"
exit
fi
for f in $1/*
do
if test -f $f
then
echo -e "\nConverting $f"
/bin/mv $f $f.old
$ICONVBIN -f $2 -t $3 $f.old > $f
else
echo -e "\nSkipping $f - not a regular file";
fi
done
ターミナルライン
Sudo convert/dir_iconv.sh convert/books CURRENT_ENCODING utf8
たぶんあなたは探しています enca
:
Encaは非常にナイーブなCharsetアナライザーです。テキストファイルの文字セットとエンコーディングを検出し、組み込みのコンバーターまたは外部ライブラリとlibiconv、librecode、cstocsなどのツールを使用して、それらを他のエンコーディングに変換することもできます。
現在、ベラルーシ語、ブルガリア語、クロアチア語、チェコ語、エストニア語、ハンガリー語、ラトビア語、リトアニア語、ポーランド語、ロシア語、スロバキア語、スロベニア語、ウクライナ語、中国語、および一部のマルチバイトエンコーディングは、言語に依存せずにサポートされています。
一般に、現在のエンコーディングの自動検出は難しいプロセスです(同じバイトシーケンスが複数のエンコーディングで正しいテキストになる場合があります)。 enca
は、検出するように指定した言語に基づいてヒューリスティックを使用します(エンコードの数を制限するため)。 enconv
to convert text files to a single encodingを使用できます。
標準のgnu utilsファイルとawkを使用して、必要なものを取得できます。例:
file -bi .xsession-errors
は私に「text/plain; charset = us-ascii」をくれます
そう file -bi .xsession-errors |awk -F "=" '{print $2}'
は "us-ascii"をくれます
私はそれを次のようなスクリプトで使用します:
CHARSET="$(file -bi "$i"|awk -F "=" '{print $2}')"
if [ "$CHARSET" != utf-8 ]; then
iconv -f "$CHARSET" -t utf8 "$i" -o outfile
fi
それらをすべてコンパイルします。 dirに移動し、dir2utf8.shを作成します。
#!/bin/bash
# converting all files in a dir to utf8
for f in *
do
if test -f $f then
echo -e "\nConverting $f"
CHARSET="$( file -bi "$f"|awk -F "=" '{print $2}')"
if [ "$CHARSET" != utf-8 ]; then
iconv -f "$CHARSET" -t utf8 "$f" -o "$f"
fi
else
echo -e "\nSkipping $f - it's a regular file";
fi
done
これがすべてのファイルを配置するための私の解決策です:
#!/bin/bash
apt-get -y install recode uchardet > /dev/null
find "$1" -type f | while read FFN # 'dir' should be changed...
do
encoding=$(uchardet "$FFN")
echo "$FFN: $encoding"
enc=`echo $encoding | sed 's#^x-mac-#mac#'`
set +x
recode $enc..UTF-8 "$FFN"
done
https://Gist.github.com/demofly/25f856a96c29b89baa32
それをconvert-dir-to-utf8.sh
に入れて実行します。
bash convert-dir-to-utf8.sh /pat/to/my/trash/dir
ここでは、sedがMacエンコーディングの回避策であることに注意してください。多くの一般的でないエンコーディングでは、このような回避策が必要です。
これが私の答えです... = D
#!/bin/bash
find <YOUR_FOLDER_PATH> -name '*' -type f -exec grep -Iq . {} \; -print0 |
while IFS= read -r -d $'\0' LINE_FILE; do
CHARSET=$(uchardet $LINE_FILE)
echo "Converting ($CHARSET) $LINE_FILE"
# NOTE: Convert/reconvert to utf8. By Questor
iconv -f "$CHARSET" -t utf8 "$LINE_FILE" -o "$LINE_FILE"
# NOTE: Remove "BOM" if exists as it is unnecessary. By Questor
# [Refs.: https://stackoverflow.com/a/2223926/3223785 ,
# https://stackoverflow.com/a/45240995/3223785 ]
sed -i '1s/^\xEF\xBB\xBF//' "$LINE_FILE"
done
# [Refs.: https://justrocketscience.com/post/handle-encodings ,
# https://stackoverflow.com/a/9612232/3223785 ,
# https://stackoverflow.com/a/13659891/3223785 ]
追加の質問:私のアプローチが最も安全かどうかわかりません。これは、一部のファイルが正しく変換されない(文字が失われる)か、「切り捨てられている」ことに気付いたためです。これは、「iconv」ツールまたは「uchardet」ツールで取得した文字セット情報に関係していると思います。 https://stackoverflow.com/a/22841847/3223785 (@demofly)で提示された解決策は、より安全である可能性があるため、私は興味を持っていました。
@demoflyの回答に基づく別の回答...
#!/bin/bash
find <YOUR_FOLDER_PATH> -name '*' -type f -exec grep -Iq . {} \; -print0 |
while IFS= read -r -d $'\0' LINE_FILE; do
CHARSET=$(uchardet $LINE_FILE)
REENCSED=`echo $CHARSET | sed 's#^x-mac-#mac#'`
echo "\"$CHARSET\" \"$LINE_FILE\""
# NOTE: Convert/reconvert to utf8. By Questor
recode $REENCSED..UTF-8 "$LINE_FILE" 2> STDERR_OP 1> STDOUT_OP
STDERR_OP=$(cat STDERR_OP)
rm -f STDERR_OP
if [ -n "$STDERR_OP" ] ; then
# NOTE: Convert/reconvert to utf8. By Questor
iconv -f "$CHARSET" -t utf8 "$LINE_FILE" -o "$LINE_FILE" 2> STDERR_OP 1> STDOUT_OP
STDERR_OP=$(cat STDERR_OP)
rm -f STDERR_OP
fi
# NOTE: Remove "BOM" if exists as it is unnecessary. By Questor
# [Refs.: https://stackoverflow.com/a/2223926/3223785 ,
# https://stackoverflow.com/a/45240995/3223785 ]
sed -i '1s/^\xEF\xBB\xBF//' "$LINE_FILE"
if [ -n "$STDERR_OP" ] ; then
echo "ERROR: \"$STDERR_OP\""
fi
STDOUT_OP=$(cat STDOUT_OP)
rm -f STDOUT_OP
if [ -n "$STDOUT_OP" ] ; then
echo "RESULT: \"$STDOUT_OP\""
fi
done
# [Refs.: https://justrocketscience.com/post/handle-encodings ,
# https://stackoverflow.com/a/9612232/3223785 ,
# https://stackoverflow.com/a/13659891/3223785 ]
再コーディングと仮想化を備えたハイブリッドソリューション...
#!/bin/bash
find <YOUR_FOLDER_PATH> -name '*' -type f -exec grep -Iq . {} \; -print0 |
while IFS= read -r -d $'\0' LINE_FILE; do
CHARSET=$(uchardet $LINE_FILE)
REENCSED=`echo $CHARSET | sed 's#^x-mac-#mac#'`
echo "\"$CHARSET\" \"$LINE_FILE\""
# NOTE: Convert/reconvert to utf8. By Questor
recode $REENCSED..UTF-8 "$LINE_FILE" 2> STDERR_OP 1> STDOUT_OP
STDERR_OP=$(cat STDERR_OP)
rm -f STDERR_OP
if [ -n "$STDERR_OP" ] ; then
# NOTE: Convert/reconvert to utf8. By Questor
bash -c "</dev/tty vim -u NONE +\"set binary | set noeol | set nobomb | set encoding=utf-8 | set fileencoding=utf-8 | wq\" \"$LINE_FILE\""
else
# NOTE: Remove "BOM" if exists as it is unnecessary. By Questor
# [Refs.: https://stackoverflow.com/a/2223926/3223785 ,
# https://stackoverflow.com/a/45240995/3223785 ]
sed -i '1s/^\xEF\xBB\xBF//' "$LINE_FILE"
fi
done
注:これは、完全な変換の数が最も多いソリューションでした。さらに、切り捨てられたファイルはありませんでした。
警告:ファイルのバックアップを作成し、マージツールを使用して変更を確認/比較します。問題が発生する可能性があります!
ヒント:コマンドsed -i '1s/^\xEF\xBB\xBF//' "$LINE_FILE"
は、「差異」を引き起こす可能性があるため、変換ツールを使用せずに、変換ツールを使用して事前に比較した後に実行できます。
注:「find」を使用した検索では、「YOUR_FOLDER_PATH」とそのサブフォルダからすべての非バイナリファイルが取得されます。
ありがとう!
Linux cliでデータ変換に利用できるツールをチェックしてください: https://www.debian.org/doc/manuals/debian-reference/ch11.en.html
また、iconv
で利用できるエンコーディングの完全なリストを見つけるための探求があります。ただ走れ iconv --list
そして、エンコーディング名がuchardet
ツールによって返される名前と異なることを確認します(例:uchardet
のx-mac-cyrillicとiconv
のmac-cyrillic)
encaコマンドは、GB2312エンコーディングの簡体字中国語テキストファイルでは機能しません。
代わりに、次の関数を使用してテキストファイルを変換します。もちろん、出力をファイルにリダイレクトすることもできます。
chardetおよびiconvコマンドが必要です。
detection_cat ()
{
DET_OUT=$(chardet $1);
ENC=$(echo $DET_OUT | sed "s|^.*: \(.*\) (confid.*$|\1|");
iconv -f $ENC $1
}