Jak określić kodowanie plików w systemie OS X?

170

Próbuję wprowadzić kilka znaków UTF-8 do pliku LaTeX w TextMate (który mówi, że jego domyślne kodowanie to UTF-8), ale LaTeX ich nie rozumie.

Uruchomienie cat my_file.texpokazuje poprawnie znaki w Terminalu. Running ls -alpokazuje coś, czego nigdy wcześniej nie widziałem: znak „@” przy liście plików:

-rw-r--r--@  1 me      users      2021 Feb 11 18:05 my_file.tex

(I tak, używam \usepackage[utf8]{inputenc}w LaTeX.)

Znalazłem iconv, ale to nie wydaje się być w stanie powiedzieć mi, jakie jest kodowanie - zostanie przekonwertowane dopiero, gdy to zrozumiem.

James A. Rosen
źródło
Z mojego doświadczenia wynika, że ​​polecenie file (1) zawsze było całkiem dobre w odgadywaniu kodowania pliku. Nie wiem, czy wystarczy użyć rozszerzonego atrybutu com.apple.TextEncoding pliku, czy nie.
Edward Falk

Odpowiedzi:

33

Te @środki, że plik rozszerzył atrybuty pliku z nim związane. Możesz zapytać o nie za pomocą getxattr()funkcji.

Nie ma określonego sposobu na wykrycie kodowania pliku. Przeczytaj odpowiedź, wyjaśnia, dlaczego.

Jest narzędzie wiersza poleceń, enca , które próbuje odgadnąć kodowanie. Może będziesz chciał to sprawdzić.

codelogic
źródło
1
Zakładałem, że OSX przechowuje kodowanie jako metadane. Zrozumiałem, że zawartość pliku była po prostu zbitką bitów i nie miała żadnego kodowania.
James A. Rosen
1
@ JamesA.Rosen OS X aplikacje, takie jak TextEdit, przechowują kodowanie plików jako atrybut (o nazwie „com.apple.TextEncoding”). Jest całkiem prawdopodobne, że wskazane przez @to atrybuty obejmują atrybut kodowania pliku. Możesz użyć polecenia, xattr -p com.apple.TextEncoding <filename>aby sprawdzić atrybut kodowania, jeśli istnieje.
bames53
1
czy możesz wyjaśnić, jak używać getxattr? Nie jestem w stanie tego użyć.
MeV,
1
To wywołanie funkcji, którego użyłbyś, gdybyś chciał napisać program. W wierszu poleceń wpisz po prostu, ls -l@ <filename>aby zobaczyć, jakie atrybuty są ustawione dla pliku. Aby zobaczyć rzeczywisty atrybut, wpiszxattr -p com.apple.TextEncoding <filename>
Edward Falk
Aby to encazrobić brew install encai musisz określić język, ale żaden nie działa, więc:enca FILENAME -L __
Shane
433

Użycie opcji -I(to duże i) w poleceniu pliku wydaje się pokazywać kodowanie pliku.

file -I {filename}
Tim
źródło
58
Musiałem użyć -I
Casebash
7
Wydawało się, że ta funkcja nie była w stanie odróżnić ASCII i UTF-8 (wydaje się, że są one takie same dla większości znaków amerykańskich, ale nie wszystkich, być może coś, co
wykryłoby
14
ASCII i UTF8 są takie same, chyba że w pliku lub w BOM znajduje się znak poza OxFF.
davidtbernal
3
file -I *wydaje się, że działa idealnie dla mnie (na OSX). System skarżył się na kodowanie jednego z wielu plików, nie określając, który. Wszystkie pliki były ascii, z wyjątkiem jednego, którym był utf-8. Najprawdopodobniej sprawca.
mcv
1
@notJim To nieprawidłowe. ASCII jest definiowane tylko przez 0x7F, więc wszystko poza tym punktem wyraźnie nie jest ASCII. Unicode i Latin-1 mają te same punkty kodowe w 0x80-0xFF, ale nie ma wspólnego kodowania Unicode, które jest identyczne z Latin-1 (ponieważ byłoby to z natury ograniczone do 8 bitów, co jest o wiele za mało dla Unicode).
tripleee
56

W systemie Mac OS X polecenie file -I(duże i) poda odpowiedni zestaw znaków, o ile testowany plik zawiera znaki spoza podstawowego zakresu ASCII.

Na przykład, jeśli wejdziesz do Terminala i użyjesz vi do utworzenia pliku, np. vi test.txt następnie wstaw kilka znaków i dołącz znak akcentowany (spróbuj ALT-e, a następnie e), a następnie zapisz plik.

Piszą file -I text.txti powinieneś otrzymać taki wynik:

test.txt: text/plain; charset=utf-8

Cloudranger
źródło
3
Mogę potwierdzić przypadek OS X, charset = us-ascii lub charset = utf-8 w zależności od zawartości pliku
Ben
ale wygląda na to, że patrzy tylko na kilka pierwszych KB pliku. w moim przypadku polecenie vim pod adresem stackoverflow.com/a/33644535/161022 poprawnie zidentyfikowało plik jako utf-8, podczas gdy filepolecenie twierdzi, że jegous-ascii
lmsurprenant
Rzeczywiście, wydaje się, że pliki oszukują ze względu na wydajność. Właśnie utworzyłem plik ASCII o wielkości 3 MB na Ubuntu i dodałem kilka znaków UTF-8 na końcu i nadal wyświetla ASCII, a nie UTF-8. Wypróbowałem opcję -k (kontynuuj), ale wtedy zgłasza „dane”, a nie „UTF-8”, więc nadal nie jest dobrze.
Cloudranger
24
vim -c 'execute "silent !echo " . &fileencoding | q' {filename}

alias gdzieś w mojej konfiguracji basha jako

alias vic="vim -c 'execute \"silent !echo \" . &fileencoding | q'"

więc po prostu piszę

vic {filename}

Na moim waniliowym OSX Yosemite daje dokładniejsze wyniki niż "plik -I":

$ file -I pdfs/udocument0.pdf
pdfs/udocument0.pdf: application/pdf; charset=binary
$ vic pdfs/udocument0.pdf
latin1
$
$ file -I pdfs/t0.pdf
pdfs/t0.pdf: application/pdf; charset=us-ascii
$ vic pdfs/t0.pdf
utf-8
jmettraux
źródło
1
To jedyna odpowiedź, która dała mi to, czego potrzebowałem - „latin1”, w przeciwieństwie do „us-ascii”. Chociaż musiałem usunąć ukośniki.
katy lavallee
Wielkie dzięki, usunąłem ukośniki.
jmettraux
21

Możesz także konwertować z jednego typu pliku na inny za pomocą następującego polecenia:

iconv -f original_charset -t new_charset originalfile > newfile

na przykład

iconv -f utf-16le -t utf-8 file1.txt > file2.txt
RPM
źródło
13

Po prostu użyj:

file -I <filename>

Otóż ​​to.

bx2
źródło
2
Nie chcę głosować przeciw, ale ta odpowiedź jest całkowicie błędna. Małe -i mówi, że nie klasyfikuj zawartości, jeśli jest to zwykły plik. -I jest równoważne --mime, które wysyła ciągi typu MIME. Narzędzia OSX zachowują się inaczej niż standardowe narzędzia Linuksa.
sillyMunky
Cóż, dla pliku zakodowanego w systemie Windows 1252 file -Idostaje mnie text/plain; charset=unknown-8bit. Choć to działa lepiej dla pliku utf8: text/plain; charset=utf-8.
MiB
8

Użycie filepolecenia z --mime-encodingopcją (np. file --mime-encoding some_file.txt) Zamiast opcji -I działa w systemie OS X i ma dodatkową zaletę polegającą na pomijaniu typu MIME „tekst / zwykły”, co prawdopodobnie nie jest dla Ciebie ważne.

Adam
źródło
ls -l @ a pokaże rozszerzone atrybuty . Patrząc na stronę podręcznika ls w Yosemite, nie widzę opcji --mime-encoding.
rstackhouse
Mówiłeś o filepoleceniu. Nie wiedziałem, że istnieje. Nowicjusz. Tak czy siak. Przepraszam za głos przeciw. SO nie pozwoli mi tego cofnąć, chyba że ktoś zmieni tę odpowiedź.
rstackhouse
4

Klasyczny 8-bitowy LaTeX jest bardzo ograniczony, jeśli chodzi o użycie znaków UTF8; w dużym stopniu zależy od kodowania używanej czcionki i dostępnych glifów, które ta czcionka ma.

Ponieważ nie podajesz konkretnego przykładu, trudno jest dokładnie wiedzieć, gdzie jest problem - niezależnie od tego, czy próbujesz użyć glifu, którego nie ma Twoja czcionka, czy też nie używasz prawidłowego kodowania czcionki w pierwszym miejsce.

Oto minimalny przykład pokazujący, jak kilka znaków UTF8 może być używanych w dokumencie LaTeX:

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage[utf8]{inputenc}
\begin{document}
‘Héllø—thêrè.’
\end{document}

Możesz mieć więcej szczęścia z kodowaniem [utf8x], ale ostrzegam, że nie jest już obsługiwane i ma pewne cechy charakterystyczne w porównaniu z [utf8] (o ile pamiętam; minęło trochę czasu, odkąd na to patrzyłem). Ale jeśli to załatwi sprawę, tylko to się liczy.

Will Robertson
źródło
3

Znak @ oznacza, że ​​plik ma rozszerzone atrybuty . xattr filepokazuje jakie atrybuty posiada, xattr -l filepokazuje też wartości atrybutów (które czasami mogą być duże - spróbuj np. xattr /System/Library/Fonts/HelveLTMMzobaczyć starodawną czcionkę, która istnieje w rozwidleniu zasobów).

Jouni K. Seppänen
źródło
2

Wpisanie file myfile.texw terminalu może czasami wskazać kodowanie i typ pliku za pomocą szeregu algorytmów i magicznych liczb. Jest to dość przydatne, ale nie licz na to, że dostarcza konkretnych lub wiarygodnych informacji.

Localizable.stringsPlik (znaleziono w zlokalizowanych aplikacji Mac OS X) jest zazwyczaj być UTF-16 plik źródłowy C.

dreamlax
źródło
1

Synalyze It! pozwala na porównanie tekstu lub bajtów we wszystkich kodowaniach oferowanych przez bibliotekę ICU . Korzystając z tej funkcji, zwykle od razu widać, która strona kodowa ma sens dla Twoich danych.

pi3
źródło
1

Możesz spróbować załadować plik do okna przeglądarki Firefox, a następnie przejść do Widok - Kodowanie znaków. Obok typu kodowania pliku powinien znajdować się znacznik wyboru.

jmdeamer
źródło
0

Którego LaTeX używasz? Kiedy używałem teTeX-a, musiałem ręcznie pobrać pakiet Unicode i dodać go do moich plików .tex:

% UTF-8 stuff
\usepackage[notipa]{ucs}
\usepackage[utf8x]{inputenc}
\usepackage[T1]{fontenc}

Teraz przeszedłem na XeTeX z pakietu TeXlive 2008 ( tutaj ), jest to jeszcze prostsze:

% UTF-8 stuff
\usepackage{fontspec}
\usepackage{xunicode}

Jeśli chodzi o wykrywanie kodowania pliku, możesz się nim bawić file(1)(ale jest to raczej ograniczone), ale jak ktoś powiedział, jest to trudne.

Keltia
źródło
0

Brutalnym sposobem sprawdzenia kodowania może być po prostu sprawdzenie pliku w edytorze szesnastkowym lub podobnym. (lub napisz program do sprawdzenia) Spójrz na dane binarne w pliku. Format UTF-8 jest dość łatwy do rozpoznania. Wszystkie znaki ASCII to pojedyncze bajty o wartościach poniżej 128 (0x80) Sekwencje wielobajtowe są zgodne ze wzorcem przedstawionym w artykule wiki

Jeśli możesz znaleźć prostszy sposób na uzyskanie programu do weryfikacji kodowania, jest to oczywiście skrót, ale jeśli wszystko inne zawiedzie, to załatwi sprawę.

jalf
źródło
0

Zaimplementowałem poniższy skrypt bash, działa u mnie.

Najpierw próbuje przejść iconvz kodowania zwróconego przez file --mime-encodingdo utf-8.

Jeśli to się nie powiedzie, przechodzi przez wszystkie kodowania i pokazuje różnicę między oryginalnym i ponownie zakodowanym plikiem. Pomija kodowania, które generują duży wynik różnicowy („duży” zgodnie z definicją MAX_DIFF_LINESzmiennej lub drugim argumentem wejściowym), ponieważ są to najprawdopodobniej nieprawidłowe kodowanie.

Jeśli w wyniku użycia tego skryptu wydarzy się coś złego, nie obwiniaj mnie. Jest rm -ftam, więc są potwory. Próbowałem zapobiec niepożądanym efektom, używając go na plikach z losowym sufiksem, ale nie składam żadnych obietnic.

Testowane na 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
Joao Encarnacao
źródło