Tôi đã thực hiện kịch bản bash dưới đây, nó hoạt động với tôi.
Nó cố gắng đầu tiên iconv
từ bảng mã trả về bởi file --mime-encoding
đếnutf-8
.
Nếu thất bại, nó đi qua tất cả các mã hóa và hiển thị độ lệch giữa tệp gốc và tệp được mã hóa lại. Nó bỏ qua các bảng mã tạo ra đầu ra khác biệt lớn ("lớn" như được định nghĩa bởiMAX_DIFF_LINES
biến hoặc đối số đầu vào thứ hai), vì đó rất có thể là mã hóa sai.
Nếu "điều xấu" xảy ra do sử dụng tập lệnh này, đừng đổ lỗi cho tôi. Có một rm -f
trong đó, vì vậy có những con quái vật. Tôi đã cố gắng ngăn chặn các tác động bất lợi bằng cách sử dụng nó trên các tệp có hậu tố ngẫu nhiên, nhưng tôi không đưa ra bất kỳ lời hứa nào.
Đã thử nghiệm trên Darwin 15.6.0.
#!/bin/bash
if [[ $# -lt 1 ]]
then
echo "ERROR: need one input argument: file of which the enconding is to be detected."
exit 3
fi
if [ ! -e "$1" ]
then
echo "ERROR: cannot find file '$1'"
exit 3
fi
if [[ $# -ge 2 ]]
then
MAX_DIFF_LINES=$2
else
MAX_DIFF_LINES=10
fi
#try the easy way
ENCOD=$(file --mime-encoding $1 | awk '{print $2}')
#check if this enconding is valid
iconv -f $ENCOD -t utf-8 $1 &> /dev/null
if [ $? -eq 0 ]
then
echo $ENCOD
exit 0
fi
#hard way, need the user to visually check the difference between the original and re-encoded files
for i in $(iconv -l | awk '{print $1}')
do
SINK=$1.$i.$RANDOM
iconv -f $i -t utf-8 $1 2> /dev/null > $SINK
if [ $? -eq 0 ]
then
DIFF=$(diff $1 $SINK)
if [ ! -z "$DIFF" ] && [ $(echo "$DIFF" | wc -l) -le $MAX_DIFF_LINES ]
then
echo "===== $i ====="
echo "$DIFF"
echo "Does that make sense [N/y]"
read $ANSWER
if [ "$ANSWER" == "y" ] || [ "$ANSWER" == "Y" ]
then
echo $i
exit 0
fi
fi
fi
#clean up re-encoded file
rm -f $SINK
done
echo "None of the encondings worked. You're stuck."
exit 3