Implementé el script bash a continuación, funciona para mí.
Primero intenta iconv
desde la codificación devuelta por file --mime-encoding
to utf-8
.
Si eso falla, pasa por todas las codificaciones y muestra la diferencia entre el archivo original y el codificado nuevamente. Se salta las codificaciones que producen una gran salida de diferencia ("grande" según lo definido por la MAX_DIFF_LINES
variable o el segundo argumento de entrada), ya que es muy probable que la codificación sea incorrecta.
Si suceden "cosas malas" como resultado del uso de este script, no me culpe. Hay una rm -f
allí, así que habrá monstruos. Traté de evitar efectos adversos al usarlo en archivos con un sufijo aleatorio, pero no estoy haciendo ninguna promesa.
Probado en 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