Utilitas Unix standar suka grep
dan diff
menggunakan beberapa heuristik untuk mengklasifikasikan file sebagai "teks" atau "biner". ( grep
Output Eg mungkin termasuk baris seperti Binary file frobozz matches
.)
Apakah ada tes yang nyaman yang dapat diterapkan dalam zsh
naskah untuk melakukan klasifikasi "teks / biner" yang serupa? (Selain sesuatu seperti grep '' somefile | grep -q Binary
.)
(Saya menyadari bahwa tes semacam itu harus heuristik, dan karena itu tidak sempurna.)
file
adalah utilitas standar dan dapat dijalankan melalui sihir file untuk menentukan jenis file dengan kemampuan terbaiknya. Ini dapat memberitahu sebagian besar format teks dan melakukan pekerjaan yang cukup baik pada format biner. Jika semua yang Anda coba lakukan adalah mencari tahu apakah suatu file adalah teks atau bukan, itulah perintah yang Anda minati.file
akan dicetak, misalnyashell script
, untuk beberapa file saya ingin diklasifikasikan sebagai "teks". Apakah ada carafile
untuk mencetak hanyatext
ataubinary
?cut
perintah mereka .file
output perpipaancut
adalah solusinya - tentu saja, ada ruang yang hilang yang membuatnya gagal dan yang telah membuat kebanyakan orang di sana membahas Y bukan X tetapi komentar dan jawaban Stéphane menunjukkan cara yang tepat untuk menentukan apakah file tersebut teks atau tidak.Jawaban:
Jika Anda
file
hanya meminta tipe mime, Anda akan mendapatkan banyak yang berbeda sepertitext/x-shellscript
, danapplication/x-executable
lain - lain, tetapi saya bayangkan jika Anda hanya memeriksa bagian "teks" Anda harus mendapatkan hasil yang baik. Misalnya (-b
tanpa keluaran nama file):sumber
file
, bahwa Anda mungkin kehilangan beberapa format teks:application/xml
(dan mirip seperti RSS),application/ecmascript
,application/json
,image/svg+xml
, ... Anda harus daftar putih mereka.application/*
tipe tidak dimaksudkan untuk konsumsi manusia, bahkan ketika mereka mungkin berbasis teks untuk memfasilitasi pengembangan dan debugging. Itu sebabnya ada atext/xml
dan aapplication/xml
. Jadi pertanyaan apakah menganggapnya sebagai teks tergantung pada kebutuhan OP.cut -d/ -f1
Pendekatan lain akan digunakan
isutf8
dari koleksi moreutils .Keluar dengan 0 jika file tersebut valid UTF-8 atau ASCII, atau korsleting, mencetak pesan kesalahan (diam dengan
-q
) dan keluar dengan 1 sebaliknya.sumber
Jika Anda menyukai heuristik yang digunakan oleh GNU
grep
, Anda bisa menggunakannya:Itu mencari NUL byte di buffer pertama yang dibaca dari file (beberapa kilo-byte untuk file biasa, tetapi bisa jauh lebih sedikit untuk pipa atau soket atau beberapa perangkat seperti
/dev/random
). Di lokal UTF-8, ia juga menandai urutan byte yang tidak membentuk karakter UTF-8 yang valid. DiasumsikanLC_ALL
tidak diatur ke sesuatu di mana bahasa itu bukan bahasa Inggris.The
${1-$REPLY}
Bentuk memungkinkan Anda untuk menggunakannya sebagaizsh
kualifikasi glob:akan daftar file biner .
sumber
Anda dapat mencoba menentukan apakah
iconv
dapat membaca file. Ini kurang berkinerja daripadafile
(yang hanya membaca beberapa byte dari awal), tetapi akan memberi Anda hasil yang lebih dapat diandalkan:Ini
iconv
pada dasarnya membuat no-op, tetapi jika ia menemukan data yang tidak valid (tidak valid UTF-8 dalam contoh ini), itu akan muntah dan keluar.sumber
-f
dan-t
bukannya GNU, opsi panjang akan membuatnya lebih portabel. Perhatikan bahwa ia akan memanggil "biner" file yang tidak dapat dibuka. Ini akan memanggil file kosong "teks".iconv
. Tapi-f
dan-t
biasanya lebih baik.Anda dapat menulis skrip yang memanggil
file
, dan menggunakan pernyataan kasus untuk memeriksa kasus yang Anda minati.Sebagai contoh
walaupun tentu saja mungkin ada banyak kasus khusus yang menarik. Hanya memeriksa
strings
salinanlibmagic
, saya melihat sekitar 200 kasus, misalnya,Beberapa menggunakan string "teks" sebagai bagian dari tipe yang berbeda, misalnya,
juga
script
bisa menjadi bagian dari kata, tetapi saya tidak melihat masalah dalam hal ini. Tetapi skrip harus memeriksa"text"
sebagai kata , bukan substring .Sebagai pengingat,
file
output tidak menggunakan deskripsi yang tepat yang akan selalu memiliki "skrip" atau "teks". Kasus khusus adalah sesuatu yang perlu dipertimbangkan. Tindak lanjut berkomentar bahwa--mime-type
bekerja sementara pendekatan ini tidak, untuk.svg
file. Namun, dalam tes saya melihat hasil ini untuk file svg:yang saya pilih setelah melihat seribu file hanya menampilkan 6 dengan "teks" di output tipe mime. Bisa dibilang, mencocokkan "xml" di akhir output tipe mime bisa lebih bermanfaat, katakanlah, daripada mencocokkan "SVG", tetapi menggunakan skrip untuk melakukan itu akan membawa Anda kembali ke saran yang dibuat di sini.
Output dari
file
memerlukan beberapa penyetelan dalam skenario baik, dan tidak 100% dapat diandalkan (itu bingung oleh beberapa skrip Perl saya, menyebutnya "data").Ada lebih dari satu implementasi dari
file
. Yang paling umum digunakan melakukan tugasnyalibmagic
, yang dapat digunakan dari program yang berbeda (mungkin tidak langsung darizsh
, meskipunpython
bisa).Menurut tabel perbandingan uji file untuk shell, Perl, Ruby, dan Python , Perl memiliki
-T
opsi yang dapat digunakan untuk memberikan informasi ini. Tapi itu tidak mencantumkan daftar fitur yang sebandingzsh
.Bacaan lebih lanjut:
sumber
file
keluaran GNU untuk file svg:SVG Scalable Vector Graphics image
tidak mengandung teks kata. Saya pikir pendekatan ini akan lebih baik daripada jawaban yang diterima untuk memeriksa tipe mime, tetapi masih melewatkan beberapa tipe.image/svg+xml
. Sebenarnya - hanya memeriksa 1000 file yang sama, hanya 6 yang keluar sebagai "teks" sesuai dengan tipe mime saja. Saya akan tetap menggunakan skrip, yang setidaknya dapat dibuat berfungsi sesuai kebutuhan.file
memiliki opsi--mime-encoding
yang mencoba mendeteksi penyandian file.Anda dapat menggunakan
file --mime-encoding | grep binary
untuk mendeteksi apakah suatu file adalah file biner. Ini berfungsi andal meskipun bisa dikacaukan oleh satu karakter yang tidak valid dalam file teks yang panjang.Sebagai contoh, saya alias
cat
ke skrip shell berikut untuk menghindari merusak terminal saya dengan secara tidak sengaja membuka file biner:sumber
Kategori arbitrer. Sebelum menjawab cara membuat klasifikasi, Anda memerlukan definisi (ketat). Untuk memiliki definisi, Anda memerlukan suatu tujuan .
Jadi, apa yang ingin Anda lakukan dengan klasifikasi itu?
sumber
akan melakukannya. Lihat dokumentasi untuk
-B
dan-T
(cari string tersebut di halaman ituThe -T and -B switches work as follows
).sumber
perl -le 'print -B $ARGV[0] ? "binary" : "text"' --
mungkin lebih jelas. Atau bahkanperl -le 'print -B $_ ? "binary" : "text", @ARGV > 1 ? "\t$_" : "" for @ARGV' --
Saya berkontribusi pada https://github.com/audreyr/binaryornot Ia belum memiliki pembungkus baris perintah (namun) tetapi ini adalah pustaka Python sederhana yang cukup mudah untuk dipanggil bahkan dari CLI. Ia menggunakan heuristik yang cukup efisien untuk menentukan apakah suatu file adalah teks atau biner.
sumber
Saya sekarang jawaban ini agak tua, tetapi saya pikir teman saya mengajari saya "retasan" yang hebat untuk melakukan ini.
Anda menggunakan
diff
perintah dan memeriksa file Anda terhadap file teks uji:$ diff filetocheck testfile.txt
Sekarang jika
filetocheck
file biner, hasilnya adalah:Binary files filetocheck and testfile.txt differ
Dengan cara ini Anda dapat memanfaatkan
diff
perintah dan misalnya menulis fungsi yang melakukan pemeriksaan dalam skrip.sumber