Come trovare la codifica di un file in Unix tramite script
Domanda
Devo trovare la codifica di tutti i file che sono inseriti in una directory. C'è un modo per trovare la codifica utilizzata?
Il comando file
non è in grado di farlo.
La codifica che mi interessa è: ISO-8859-1. Se la codifica è qualcos'altro, voglio spostare il file in un'altra directory.
Soluzione
Sembra che tu stia cercando enca
. Può indovinare e persino convertire tra codifiche. Guarda la pagina man .
Oppure, in mancanza, utilizzare file -i
(linux) o file -I
(osx). Ciò genererà informazioni di tipo MIME per il file, che includerà anche la codifica del set di caratteri. Ho trovato anche una man-page anche per questo :)
Altri suggerimenti
file -bi <file name>
Se ti piace farlo per un mucchio di file
for f in `find | egrep -v Eliminate`; do echo "$f" ' -- ' `file -bi "$f"` ; done
uchardet - Una libreria di rilevatori di codifica trasferita da Mozilla.
Utilizzo:
~> uchardet file.java
UTF-8
Varie distribuzioni Linux (Debian / Ubuntu, OpenSuse-packman, ...) forniscono file binari.
ecco uno script di esempio che utilizza il file -I e iconv che funziona su MacOsX Per la tua domanda devi usare mv invece di iconv
#!/bin/bash
# 2016-02-08
# check encoding and convert files
for f in *.java
do
encoding=`file -I $f | cut -f 2 -d";" | cut -f 2 -d=`
case $encoding in
iso-8859-1)
iconv -f iso8859-1 -t utf-8 $f > $f.utf8
mv $f.utf8 $f
;;
esac
done
È davvero difficile determinare se è iso-8859-1. Se hai un testo con soli caratteri a 7 bit che potrebbe anche essere iso-8859-1 ma non lo sai. Se si dispone di caratteri a 8 bit, esistono anche i caratteri della regione superiore anche nelle codifiche dell'ordine. Quindi dovresti usare un dizionario per capire meglio quale parola sia e determinare da lì quale lettera deve essere. Infine, se rilevi che potrebbe essere utf-8 di quanto sei sicuro che non sia iso-8859-1
La codifica è una delle cose più difficili da fare perché non si sa mai se nulla ti dice
Con Python puoi utilizzare il modulo chardet: https://github.com/chardet/chardet
In Debian puoi anche usare: encguess
:
$ encguess test.txt
test.txt US-ASCII
Questo non è qualcosa che puoi fare in modo infallibile. Una possibilità sarebbe quella di esaminare tutti i caratteri nel file per assicurarsi che non contenga caratteri negli intervalli 0x00 - 0x1f
o 0x7f -0x9f
ma, come ho detto, questo può essere vero per qualsiasi numero di file, incluso almeno un'altra variante di ISO8859.
Un'altra possibilità è cercare parole specifiche nel file in tutte le lingue supportate e vedere se riesci a trovarle.
Quindi, ad esempio, trova l'equivalente dell'inglese " e " ;, " ma " ;, " in " ;, " quot del &; e così via in tutte le lingue supportate di 8859-1 e vedere se hanno un gran numero di occorrenze all'interno del file.
Non sto parlando di una traduzione letterale come:
English French
------- ------
of de, du
and et
the le, la, les
sebbene sia possibile. Sto parlando di parole comuni nella lingua di destinazione (per quanto ne so, l'islandese non ha parole per & Quot; e & Quot; - probabilmente dovresti usare la loro parola per & Quot; fish " [scusate se è un po 'stereotipato, non intendevo alcuna offesa, sto solo illustrando un punto]).
Se stai parlando di file XML (ISO-8859-1), la dichiarazione XML al loro interno specifica la codifica: <?xml version="1.0" encoding="ISO-8859-1" ?>
Pertanto, puoi utilizzare le espressioni regolari (ad es. Con perl
) per controllare ogni file per tale specifica.
Ulteriori informazioni sono disponibili qui: Come determinare la codifica dei file di testo .
Per convertire la codifica da 8859 a ASCII:
iconv -f ISO_8859-1 -t ASCII filename.txt
So che sei interessato a una risposta più generale, ma ciò che è buono in ASCII di solito è buono in altre codifiche. Ecco un one-liner Python per determinare se l'input standard è ASCII. (Sono abbastanza sicuro che funzioni in Python 2, ma l'ho provato solo su Python 3.)
python -c 'from sys import exit,stdin;exit()if 128>max(c for l in open(stdin.fileno(),"b") for c in l) else exit("Not ASCII")' < myfile.txt
In Cygwin, sembra che funzioni per me:
find -type f -name "<FILENAME_GLOB>" | while read <VAR>; do (file -i "$<VAR>"); done
Esempio:
find -type f -name "*.txt" | while read file; do (file -i "$file"); done
Potresti reindirizzarlo a awk e creare un comando iconv per convertire tutto in utf8, da qualsiasi codifica sorgente supportata da iconv.
Esempio:
find -type f -name "*.txt" | while read file; do (file -i "$file"); done | awk -F[:=] '{print "iconv -f "$3" -t utf8 \""$1"\" > \""$1"_utf8\""}' | bash
Puoi estrarre la codifica di un singolo file con il comando file. Ho un file sample.html con:
$ file sample.html
sample.html: documento HTML, testo Unicode UTF-8, con righe molto lunghe
$ file -b sample.html
Documento HTML, testo Unicode UTF-8, con righe molto lunghe
$ file -bi sample.html
text / html; charset = utf-8
$ file -bi sample.html | awk -F'=' '{print $2 }'
UTF-8
Sto usando il seguente script per
- Trova tutti i file che corrispondono a FILTER con SRC_ENCODING
- Creane un backup
- Convertili in DST_ENCODING
- (opzionale) Rimuovi i backup
.
#!/bin/bash -xe
SRC_ENCODING="iso-8859-1"
DST_ENCODING="utf-8"
FILTER="*.java"
echo "Find all files that match the encoding $SRC_ENCODING and filter $FILTER"
FOUND_FILES=$(find . -iname "$FILTER" -exec file -i {} \; | grep "$SRC_ENCODING" | grep -Eo '^.*\.java')
for FILE in $FOUND_FILES ; do
ORIGINAL_FILE="$FILE.$SRC_ENCODING.bkp"
echo "Backup original file to $ORIGINAL_FILE"
mv "$FILE" "$ORIGINAL_FILE"
echo "converting $FILE from $SRC_ENCODING to $DST_ENCODING"
iconv -f "$SRC_ENCODING" -t "$DST_ENCODING" "$ORIGINAL_FILE" -o "$FILE"
done
echo "Deleting backups"
find . -iname "*.$SRC_ENCODING.bkp" -exec rm {} \;
Con Perl, utilizzare Encode :: Detect.