Làm cách nào để tìm mã hóa tệp qua tập lệnh trên Linux?


303

Tôi cần tìm mã hóa của tất cả các tệp được đặt trong một thư mục. Có cách nào để tìm mã hóa được sử dụng?

Các filelệnh không có khả năng để làm điều này.

Mã hóa mà tôi quan tâm là: ISO-8859-1. Nếu mã hóa là bất cứ điều gì khác, tôi muốn di chuyển tệp sang thư mục khác.


1
Nếu bạn có ý tưởng về loại ngôn ngữ kịch bản nào bạn có thể muốn sử dụng, hãy gắn thẻ câu hỏi của bạn với tên của ngôn ngữ đó. Điều đó có thể giúp ...
MatrixFrog

1
Hoặc có lẽ anh ta chỉ đang cố gắng xây dựng một kịch bản shell?
Shalom Craimer

1
Đó sẽ là một câu trả lời cho ngôn ngữ kịch bản mà ngôn ngữ.
bignose

7
Có thể không liên quan đến câu trả lời này, nhưng một mẹo chung: Khi bạn có thể mô tả toàn bộ nghi ngờ của mình bằng một từ ("mã hóa", ở đây), chỉ cần làm apropos encoding. Nó tìm kiếm các tiêu đề và mô tả của tất cả các trang. Khi tôi làm điều này trên máy tính của tôi, tôi thấy 3 công cụ có thể giúp tôi, xét xử của giới thiệu của họ: chardet, chardet3, chardetect3. Sau đó, bằng cách làm man chardetvà đọc manpage cho tôi biết đó chardetchỉ là tiện ích tôi cần.
John Red

1
Mã hóa có thể thay đổi khi bạn thay đổi nội dung của tệp. ví dụ: Trong vi, khi viết một chương trình c đơn giản, có thể us-ascii, nhưng sau khi thêm một dòng bình luận tiếng Trung, nó sẽ trở thành utf-8. filecó thể nói mã hóa bằng cách đọc nội dung tập tin và đoán.
Eric Wang

Câu trả lời:


419

Âm thanh như bạn đang tìm kiếm enca. Nó có thể đoán và thậm chí chuyển đổi giữa các bảng mã. Chỉ cần nhìn vào trang người đàn ông .

Hoặc, không thành công, sử dụng file -i(linux) hoặc file -I(osx). Điều đó sẽ xuất thông tin kiểu MIME cho tệp, cũng sẽ bao gồm mã hóa tập ký tự. Tôi cũng tìm thấy một trang dành cho nó :)


1
Theo trang người đàn ông, nó biết về bộ ISO 8559. Có lẽ đọc ít hơn một chút con trỏ :-)
bignose

5
Enca nghe có vẻ thú vị. Thật không may, phát hiện dường như rất phụ thuộc vào ngôn ngữ và tập hợp các ngôn ngữ được hỗ trợ không phải là rất lớn. Của tôi (de) bị thiếu :-( Dù sao công cụ tuyệt vời.
er4z0r

1
Bài đăng tốt trên các công cụ như enca, enconv, convmv
GuruM

6
encadường như hoàn toàn vô dụng để phân tích một tập tin được viết bằng tiếng Anh, nhưng nếu bạn tình cờ nhìn vào một cái gì đó bằng tiếng Estonia, nó có thể giải quyết tất cả các vấn đề của bạn. Công cụ rất hữu ích, đó là ... </ mỉa mai>
cbmanica

6
@vladkras nếu không có ký tự không phải mã ascii trong tệp utf-8 của bạn, thì nó không thể phân biệt được với ascii :)
vadipp

85
file -bi <file name>

Nếu bạn muốn làm điều này cho một loạt các tập tin

for f in `find | egrep -v Eliminate`; do echo "$f" ' -- ' `file -bi "$f"` ; done

Tuy nhiên, nếu tệp là tệp xml, với thuộc tính "mã hóa = 'iso-8859-1' trong khai báo xml, lệnh tệp sẽ cho biết đó là tệp iso, ngay cả khi mã hóa thực sự là utf-8 ...
Mỗi

6
Tại sao bạn sử dụng đối số -b? Nếu bạn chỉ làm tập tin -i *, nó sẽ xuất ra bộ ký tự đoán cho mọi tập tin.
Hans-Peter Störr

4
Tôi đã tò mò về đối số -b quá. Trang nam cho biết nó có nghĩa là "ngắn gọn"Do not prepend filenames to output lines
craq

1
Không cần phân tích đầu ra tệp, file -b --mime-encodingchỉ xuất ra mã hóa bộ ký tự
jesjimher

-b là viết tắt của 'be brief', về cơ bản có nghĩa là không xuất tên tệp bạn vừa đặt.
Nikos

36

uchardet - Một thư viện phát hiện mã hóa được chuyển từ Mozilla.

Sử dụng:

~> uchardet file.java 
UTF-8

Các bản phân phối Linux khác nhau (Debian / Ubuntu, OpenSuse-packman, ...) cung cấp các tệp nhị phân.


1
Cảm ơn! Tôi không hài lòng về nhiều gói hơn, nhưng sudo apt-get install uchardetnó dễ đến mức tôi quyết định không lo lắng về nó ...
hiền nhân

Như tôi vừa nói trong một nhận xét ở trên: uchardet đã nói sai cho tôi mã hóa của một tệp là "windows-1252", mặc dù tôi đã lưu rõ ràng tệp đó là UTF-8. uchardet thậm chí không nói "với sự tự tin 0.4641618497109827" mà ít nhất sẽ cho bạn một gợi ý rằng nó nói với bạn hoàn toàn vô nghĩa. tập tin, enca và encguess làm việc chính xác.
Algoman

uchardetcó một lợi thế lớn hơn fileenca, trong đó nó phân tích toàn bộ tệp (chỉ thử với tệp 20GiB), trái ngược với chỉ bắt đầu.
tuxayo

10

đây là tập lệnh ví dụ sử dụng tệp -I và iconv hoạt động trên MacOsX Đối với câu hỏi của bạn, bạn cần sử dụng mv thay vì 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

6
file -b --mime-encodingchỉ xuất ra bộ ký tự, vì vậy bạn có thể tránh mọi xử lý đường ống
jesjimher

1
Cám ơn. Như đã chỉ ra trên MacOS, điều này sẽ không hoạt động: file -b --mime-mã hóa Cách sử dụng: file [-bchikLNnprsvz0] [-e test] [-f namefile] [-F separator] [-m magicfiles] [-M magicfiles] ] tập tin ... tập tin -C -m Magicfiles Hãy thử 'tập tin - trợ giúp' để biết thêm thông tin.
Wolfgang Fahl

6

Thật sự rất khó để xác định nếu nó là iso-8859-1. Nếu bạn có một văn bản chỉ có 7 ký tự cũng có thể là iso-8859-1 nhưng bạn không biết. Nếu bạn có các ký tự 8 bit thì các ký tự vùng trên cũng tồn tại theo thứ tự mã hóa. Do đó, bạn sẽ phải sử dụng một từ điển để đoán từ đó là từ nào và xác định từ đó phải là chữ cái nào. Cuối cùng nếu bạn phát hiện ra rằng nó có thể là utf-8 thì bạn chắc chắn đó không phải là iso-8859-1

Mã hóa là một trong những điều khó nhất để làm bởi vì bạn không bao giờ biết nếu không có gì đang nói với bạn


Nó có thể giúp để cố gắng vũ phu. Lệnh sau sẽ cố gắng chuyển đổi từ tất cả các định dạng mã hóa với tên bắt đầu bằng WIN hoặc ISO thành UTF8. Sau đó, người ta sẽ cần phải kiểm tra thủ công đầu ra để tìm kiếm một đầu mối vào mã hóa đúng. Tất nhiên, bạn có thể thay đổi các định dạng được lọc thay thế ISO hoặc WIN cho thứ gì đó phù hợp hoặc xóa bộ lọc bằng cách xóa lệnh grep. cho i bằng $ (iconv -l | tail -n +2 | grep "(^ ISO \ | ^ WIN)" | sed -e 's / \ / \ ///'); làm vang $ i; iconv -f $ i -t santos UTF8; làm xong;
ndvo

5

Trong Debian bạn cũng có thể sử dụng encguess::

$ encguess test.txt
test.txt  US-ASCII

Tôi đã cài đặt uchardettrong Ubuntu và nó nói với tôi rằng tập tin của tôi là WINDOWS-1252. Tôi biết điều này là sai vì tôi đã lưu nó dưới dạng UTF-16 với Kate, để kiểm tra. Tuy nhiên, hãy encguessđoán chính xác và nó đã được cài đặt sẵn trong Ubuntu 19.04.
Nagev

5

Để chuyển đổi mã hóa từ 8859 sang ASCII:

iconv -f ISO_8859-1 -t ASCII filename.txt

4

Với Python, bạn có thể sử dụng mô-đun chardet: https://github.com/chardet/chardet


Tên miền không tồn tại: feedparser.org
Rune

Theo nhận xét này, nó vẫn có sẵn trên Github: github.com/dcramer/chardet
Rick Hanlon II

Theo nhận xét này, đó là trên chardet / chardet trên github. Cập nhật câu trả lời.
Quentin Pradet

chardet báo cáo "Không", chardet3 cuộn cảm trên dòng đầu tiên của tệp theo cách chính xác giống như tập lệnh python của tôi.
Joels Elf

3

Đây không phải là điều bạn có thể làm một cách dễ dàng. Một khả năng sẽ là kiểm tra mọi ký tự trong tệp để đảm bảo rằng nó không chứa bất kỳ ký tự nào trong phạm vi 0x00 - 0x1fhoặc 0x7f -0x9f, như tôi đã nói, điều này có thể đúng với bất kỳ số lượng tệp nào, bao gồm ít nhất một biến thể khác của ISO8859.

Một khả năng khác là tìm kiếm các từ cụ thể trong tệp bằng tất cả các ngôn ngữ được hỗ trợ và xem bạn có thể tìm thấy chúng không.

Vì vậy, ví dụ, tìm tương đương với tiếng Anh "và", "nhưng", "đến", "của" trong tất cả các ngôn ngữ được hỗ trợ của 8859-1 và xem liệu chúng có số lần xuất hiện lớn trong tập tin.

Tôi không nói về dịch nghĩa đen như:

English   French
-------   ------
of        de, du
and       et
the       le, la, les

mặc dù điều đó là có thể Tôi đang nói về những từ phổ biến trong ngôn ngữ đích (đối với tất cả những gì tôi biết, tiếng Iceland không có từ "và" - có lẽ bạn phải sử dụng từ "cá" [xin lỗi đó là một chút rập khuôn, tôi đã không có nghĩa là bất kỳ hành vi phạm tội, chỉ minh họa một điểm]).


2

Tôi biết bạn quan tâm đến một câu trả lời tổng quát hơn, nhưng những gì tốt trong ASCII thường tốt trong các bảng mã khác. Dưới đây là một lớp lót Python để xác định xem đầu vào tiêu chuẩn có phải là ASCII không. (Tôi khá chắc chắn rằng điều này hoạt động trong Python 2, nhưng tôi chỉ thử nghiệm nó trên 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

2

Nếu bạn đang nói về các tệp XML (ISO-8859-1), khai báo XML bên trong chúng chỉ định mã hóa: <?xml version="1.0" encoding="ISO-8859-1" ?>
Vì vậy, bạn có thể sử dụng các biểu thức chính quy (ví dụ với perl) để kiểm tra mọi tệp cho thông số kỹ thuật đó.
Thông tin chi tiết có thể được tìm thấy ở đây: Cách xác định mã hóa tệp văn bản .


tốt, dòng đó có thể được sao chép-dán bởi một người không biết anh ta đang sử dụng mã hóa nào.
Algoman

Lưu ý, không có gì về khai báo ở trên cùng đảm bảo tệp HOẠT ĐỘNG được mã hóa theo cách đó. Nếu bạn thực sự, thực sự quan tâm đến mã hóa bạn cần phải xác nhận nó.
Jazzepi

2

Trong php bạn có thể kiểm tra như dưới đây:

Chỉ định danh sách mã hóa rõ ràng:

php -r "echo 'probably : ' . mb_detect_encoding(file_get_contents('myfile.txt'), 'UTF-8, ASCII, JIS, EUC-JP, SJIS, iso-8859-1') . PHP_EOL;"

Chính xác hơn "mb_list_encodings":

php -r "echo 'probably : ' . mb_detect_encoding(file_get_contents('myfile.txt'), mb_list_encodings()) . PHP_EOL;"

Ở đây trong ví dụ đầu tiên, bạn có thể thấy rằng tôi đặt một danh sách các bảng mã (phát hiện thứ tự danh sách) có thể khớp. Để có kết quả chính xác hơn, bạn có thể sử dụng tất cả các mã hóa có thể thông qua: mb_list_encodings ()

Lưu ý các hàm mb_ ​​* yêu cầu php-mbopes

apt-get install php-mbstring

0

Trong Cygwin, điều này có vẻ như nó hoạt động với tôi:

find -type f -name "<FILENAME_GLOB>" | while read <VAR>; do (file -i "$<VAR>"); done

Thí dụ:

find -type f -name "*.txt" | while read file; do (file -i "$file"); done

Bạn có thể chuyển nó thành awk và tạo một lệnh iconv để chuyển đổi mọi thứ thành utf8, từ bất kỳ mã hóa nguồn nào được iconv hỗ trợ.

Thí dụ:

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

0

Bạn có thể trích xuất mã hóa của một tệp bằng lệnh tệp. Tôi có tệp sample.html với:

$ file sample.html 

sample.html: Tài liệu HTML, văn bản Unicode UTF-8, với các dòng rất dài

$ file -b sample.html

Tài liệu HTML, văn bản Unicode UTF-8, với các dòng rất dài

$ file -bi sample.html

văn bản / html; bộ ký tự = utf-8

$ file -bi sample.html  | awk -F'=' '{print $2 }'

utf-8


1
đầu ra tôi nhận được chỉ là "tệp thông thường"
Mordechai

0

Tôi đang sử dụng đoạn script sau để

  1. Tìm tất cả các tệp khớp với LỌC với SRC_ENCODING
  2. Tạo một bản sao lưu của chúng
  3. Chuyển đổi chúng thành DST_ENCODING
  4. (tùy chọn) Xóa các bản sao lưu

.

#!/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 {} \;

0

với lệnh này:

for f in `find .`; do echo `file -i "$f"`; done

bạn có thể liệt kê tất cả các tệp trong một thư mục và thư mục con và mã hóa tương ứng.


-2

Với Perl, sử dụng Encode :: Detect.


7
Bạn có thể cho một ví dụ làm thế nào để sử dụng nó trong vỏ?
Lri

Một poster khác (@fccoelho) đã cung cấp một mô-đun Python như một giải pháp đạt +3 và áp phích này nhận được -2 cho một câu trả lời rất giống nhau ngoại trừ đó là cho mô-đun Perl. Tại sao tiêu chuẩn kép?!
Happy Green Kid Naps

4
Có lẽ một ví dụ mã của một perl liner sẽ giúp câu trả lời này.
vikingsteve
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.