क्या फ़ाइलों को "बाइनरी" या "टेक्स्ट" के रूप में वर्गीकृत करने का एक सुविधाजनक तरीका है?


35

जैसे मानक, यूनिक्स उपयोगिताओं grepऔर diff"पाठ" या "बाइनरी" के रूप में वर्गीकृत फ़ाइलों के लिए कुछ अनुमानी का उपयोग करें। (उदाहरण grepके आउटपुट में लाइनें शामिल हो सकती हैं Binary file frobozz matches)

क्या एक सुविधाजनक परीक्षण एक zshस्क्रिप्ट में एक समान "टेक्स्ट / बाइनरी" वर्गीकरण करने के लिए आवेदन कर सकता है? (जैसे कुछ के अलावा अन्य grep '' somefile | grep -q Binary)

(मुझे पता है कि इस तरह के किसी भी परीक्षण के लिए जरूरी है, और इसलिए अपूर्ण होगा।)


10
fileएक मानक उपयोगिता है और फ़ाइल मैजिक को अपनी क्षमताओं के अनुसार फ़ाइल प्रकारों के निर्धारण के लिए चला सकते हैं। यह अधिकांश पाठ प्रारूपों को बता सकता है और द्विआधारी प्रारूपों पर बहुत अच्छा काम करता है। यदि आप सब करने की कोशिश कर रहे हैं, तो यह पता करें कि क्या कोई फाइल टेक्स्ट है या नहीं, यह वह कमांड है जिसमें आप रुचि रखते हैं।
ब्राचली

@ ब्रेचली: कुछ संस्करणों की fileछपाई होगी, उदाहरण के लिए shell script, कुछ फाइलों के लिए जिन्हें मैं "पाठ" के रूप में वर्गीकृत करूंगा। वहाँ fileसिर्फ पाने के लिए एक रास्ता है textया binary?
कोजो

1
@don_crissti यह सवाल किसी के बारे में है जो लोगों को उसकी बैश स्क्रिप्ट को हटाने की कोशिश कर रहा है। पाठ का पता लगाना सिर्फ वही है जो स्क्रिप्ट को करना है। उन्होंने अपने एक cutआदेश में एक मुद्दा समाप्त कर दिया ।
ब्राचली

1
@don_crissti तथ्य यह है कि प्रश्न A पर एक उत्तर है जो प्रश्न B के लिए काम करता है, हमेशा A को B का डुप्लिकेट नहीं बनाता है। किसी ऐसे व्यक्ति पर विचार करें जो फ़ाइलों को पाठ या बाइनरी के रूप में वर्गीकृत करने का तरीका खोज रहा है। जो अधिक उपयोगी है: एक "मेरी स्क्रिप्ट को डीबग करें" सवाल जो अन्य उत्तरों के बीच एक सामान्य उत्तर को दफनाने के लिए होता है, जो उस स्क्रिप्ट के लिए विशिष्ट है, या एक सामान्य "मैं कैसे पाठ या द्विआधारी के रूप में फ़िसेल वर्गीकृत करता हूं?"
गिल्स एसओ- बुराई को रोकना '

1
@ गिल्स - इस पर निर्भर करता है कि आप इसे कैसे पढ़ते हैं। मैं वास्तव में XY समस्या के एक विशिष्ट मामले के रूप में प्रश्न को देखता हूं: ओपी वहां यह जांचना चाहता है कि क्या कोई फ़ाइल एक पाठ फ़ाइल है - और सोचता है कि पाइपिंग fileआउटपुट cutसमाधान है - निश्चित रूप से, एक लापता स्थान है जो इसे विफल बनाता है और जिसने इसे बनाया है अधिकांश लोग X के बजाय Y को संबोधित करते हैं लेकिन स्टीफन की टिप्पणी और उत्तर यह निर्धारित करने के लिए उचित तरीका दिखाते हैं कि फाइल पाठ है या नहीं।
21_15 पर don_crissti

जवाबों:


27

यदि आप fileसिर्फ माइम-प्रकार के लिए पूछते हैं , तो आपको कई अलग-अलग जैसे text/x-shellscriptऔर application/x-executableआदि मिलेंगे , लेकिन मुझे लगता है कि अगर आप सिर्फ "टेक्स्ट" भाग की जांच करते हैं तो आपको अच्छे परिणाम मिलने चाहिए। जैसे ( -bआउटपुट में कोई फ़ाइल नाम नहीं):

file -b --mime-type filename | sed 's|/.*||'

24
बस याद रखें, अपने पर निर्भर करता है file, कि आप कुछ पाठ प्रारूपों से छूट सकते हैं: application/xml(और राष्ट्रीय स्वयंसेवक संघ की तरह समान), application/ecmascript, application/json, image/svg+xml, ... आपने श्वेतसूची में उन होगा।
बोल्डविन

@ बोल्डवेन वाह, अच्छे उदाहरण! तो शायद एक बेहतर जवाब किसी भी फ़ाइल को स्वीकार करने के लिए है जिसमें केवल मुद्रण योग्य वर्ण हैं, लेकिन किसी भी तरह utf-8 और इसी तरह की एन्कोडिंग समस्याओं का सामना करना पड़ता है।
मयूह

हां, यह मेरे उत्तर का सार है। केवल समस्या यह है, कि समाधान को पूरी फ़ाइल को देखना है ...
बोल्डविन

7
@Boldewyn सिद्धांत रूप में, application/*प्रकार मानव उपभोग के लिए अभिप्रेत नहीं हैं, तब भी जब वे विकास और डिबगिंग की सुविधा के लिए पाठ-आधारित हो सकते हैं। इसीलिए a text/xmlऔर a दोनों है application/xml। इसलिए यह सवाल कि क्या उन्हें पाठ माना जाए, यह ओपी की जरूरतों पर निर्भर करता है।
टोबिया


20

एक और तरीका यह होगा isutf8कि मोरटाइल संग्रह से उपयोग किया जाएगा ।

यदि फ़ाइल मान्य UTF-8 या ASCII या शॉर्ट सर्किट है, तो यह 0 से बाहर निकलता है, एक त्रुटि संदेश (साथ चुप्पी -q) प्रिंट करता है और 1 के साथ बाहर निकलता है।


5
अच्छा सुझाव है। मैंने अभी देखा कि arg के रूप में एक डायरेक्टरी देने से यह 0. वापस हो जाता है। मैंने कम से कम 1 को प्राथमिकता दी होगी। लेकिन फिर, कचरा, कचरा बाहर।
meuh

13

यदि आप GNU द्वारा उपयोग किए गए अनुमानी को पसंद करते हैं grep, तो आप इसका उपयोग कर सकते हैं:

isbinary() {
  LC_MESSAGES=C grep -Hm1 '^' < "${1-$REPLY}" | grep -q '^Binary'
}

यह फ़ाइल से पढ़े गए पहले बफर में एनयूएल बाइट्स की खोज करता है (एक नियमित फ़ाइल के लिए कुछ किलो-बाइट्स, लेकिन एक पाइप या सॉकेट या जैसे कुछ उपकरणों के लिए बहुत कम हो सकता है /dev/random)। UTF-8 स्थानों में, यह बाइट अनुक्रमों पर भी फ़्लैग करता है जो मान्य UTF-8 वर्ण नहीं बनाते हैं। यह मान लिया LC_ALLजाता है कि कोई ऐसी चीज़ नहीं है जहाँ भाषा अंग्रेजी नहीं है।

${1-$REPLY}फ़ॉर्म आपको एक के रूप में उपयोग करने की अनुमति देता zshग्लोब क्वालीफायर:

ls -ld -- *(.+isbinary)

बाइनरी फ़ाइलों को सूचीबद्ध करेगा ।


7

यदि आप iconvफ़ाइल को पढ़ सकते हैं, तो आप यह निर्धारित करने का प्रयास कर सकते हैं। यह कम प्रदर्शन की तुलना में कम है file(जो शुरुआत से ही युगल बाइट्स को पढ़ता है), लेकिन आपको अधिक विश्वसनीय परिणाम देगा:

ENCODING=utf-8
if iconv --from-code="$ENCODING" --to-code="$ENCODING" your_file.ext > /dev/null 2>&1; then
    echo text
else
    echo binary
fi

यह iconvमूल रूप से एक नो-ऑप बनाता है , लेकिन यदि यह अमान्य डेटा (इस उदाहरण में अमान्य UTF-8) का सामना करता है, तो यह बारफ और बाहर निकलेगा।


4
का उपयोग करते हुए -fऔर -tबजाय जीएनयू लंबे विकल्पों में से यह अधिक पोर्टेबल होगा। ध्यान दें कि यह उन फ़ाइलों को "बाइनरी" कहेगा जो इसे नहीं खोल सकते। यह खाली फ़ाइलों को "पाठ" कहेगा।
स्टीफन चेजलस

माना। जो लोग नहीं जानते, उनके लिए मैंने तदर्थ प्रलेखन के लिए लंबे रूपों का उपयोग किया iconv। लेकिन -fऔर -tआमतौर पर बेहतर होते हैं।
बोल्ड्यूविन

7

आप एक स्क्रिप्ट लिख सकते हैं जो कॉल करता है file, और उन मामलों की जांच करने के लिए केस-स्टेटमेंट का उपयोग करें, जिनमें आप रुचि रखते हैं।

उदाहरण के लिए

#!/bin/sh
case $(file "$1") in
(*script*|*\ text|*\ text\ *)
    echo text
    ;;
(*)
    echo binary
    ;;
esac

हालांकि निश्चित रूप से कई विशेष मामले हो सकते हैं जो कि रुचि के हों। बस की stringsएक प्रति पर जाँच libmagic, मैं लगभग 200 मामलों को देखता हूं, जैसे,

Konqueror cookie text
Korn shell script text executable
LaTeX 2e document text
LaTeX document text
Linux Software Map entry text
Linux Software Map entry text (new format)
Linux kernel symbol map text
Lisp/Scheme program text
Lua script text executable
LyX document text
M3U playlist text
M4 macro processor script text

कुछ स्ट्रिंग "टेक्स्ट" का उपयोग एक अलग प्रकार के भाग के रूप में करते हैं, जैसे,

SoftQuad troff Context intermediate   
SoftQuad troff Context intermediate for AT&T 495 laser printer
SoftQuad troff Context intermediate for HP LaserJet

इसी तरह scriptएक शब्द का हिस्सा हो सकता है, लेकिन मुझे इस मामले में कोई समस्या नहीं है। लेकिन एक स्क्रिप्ट के लिए जाँच करनी चाहिए "text"एक के रूप में शब्द , न कि एक -स्ट्रिंग

अनुस्मारक के रूप में, file आउटपुट एक सटीक विवरण का उपयोग नहीं करता है जिसमें हमेशा "स्क्रिप्ट" या "पाठ" होगा। विशेष मामलों पर विचार करने के लिए कुछ कर रहे हैं। एक फॉलोअप ने टिप्पणी की कि यह --mime-typeकार्य .svgफाइलों के लिए नहीं होगा । हालाँकि, एक परीक्षण में मैं इन परिणामों को svg-files के लिए देखता हूँ:

$ ls -l *.svg
-r--r--r-- 1 tom users  6679 Jul 26  2012 pumpkin_48x48.svg
-r--r--r-- 1 tom users 17372 Jul 30  2012 sink_48x48.svg
-r--r--r-- 1 tom users  5929 Jul 25  2012 vile_48x48.svg
-r--r--r-- 1 tom users  3553 Jul 28  2012 vile-mini.svg
$ file *.svg
pumpkin_48x48.svg: SVG Scalable Vector Graphics image
sink_48x48.svg:    SVG Scalable Vector Graphics image
vile-mini.svg:     SVG Scalable Vector Graphics image
vile_48x48.svg:    SVG Scalable Vector Graphics image
$ file --mime-type *.svg
pumpkin_48x48.svg: image/svg+xml
sink_48x48.svg:    image/svg+xml
vile-mini.svg:     image/svg+xml
vile_48x48.svg:    image/svg+xml

जिसे मैंने एक हजार फाइलों को देखने के बाद चुना था, माइम-टाइप आउटपुट में "टेक्स्ट" के साथ केवल 6 दिखाते हैं। तर्क से, "एसवीजी" मिलान की तुलना में, माइम-प्रकार के आउटपुट के अंत में "xml" का मिलान अधिक उपयोगी हो सकता है, कहते हैं, लेकिन एक स्क्रिप्ट का उपयोग करना जो आपको यहां दिए गए सुझाव पर वापस ले जाता है।

आउटपुट fileको किसी भी परिदृश्य में कुछ ट्यूनिंग की आवश्यकता होती है, और यह 100% विश्वसनीय नहीं है (यह मेरे कई पर्ल स्क्रिप्ट्स द्वारा भ्रमित है, उन्हें "डेटा" कहते हैं)।

के एक से अधिक कार्यान्वयन है file। सबसे अधिक इस्तेमाल किया जाने वाला अपना काम करता हैlibmagic , जिसका उपयोग विभिन्न कार्यक्रमों (शायद सीधे नहीं zsh, हालांकि pythonकर सकते हैं) से किया जा सकता है।

इसके अनुसार शेल, पर्ल, रूबी और पायथन के फाइल टेस्ट तुलना तालिका के , पर्ल के पास एक -Tविकल्प है जिसका उपयोग वह अपनी जानकारी प्रदान करने के लिए कर सकता है। लेकिन इसके लिए कोई तुलनीय सुविधा नहीं है zsh

आगे की पढाई:


दुर्भाग्य से filesvg फ़ाइलों के लिए GNU का आउटपुट: SVG Scalable Vector Graphics imageशब्द पाठ शामिल नहीं है। मुझे लगा कि यह दृष्टिकोण माइम-प्रकार की जाँच के स्वीकृत उत्तर से बेहतर होगा, लेकिन यह अभी भी कुछ प्रकारों को याद करता है।
पीटर कॉर्डेस

यह अभी भी याद करता है, माइम-प्रकार के साथ; Xterm के svg फ़ाइल के लिए मुझे मिलता है image/svg+xml। वास्तव में - सिर्फ एक 1000-फ़ाइल की जाँच की, केवल 6 चूने-प्रकार के अनुसार "पाठ" के रूप में सामने आया। मैं एक स्क्रिप्ट के साथ रहूँगा, जिसे कम से कम आवश्यकतानुसार काम करने के लिए बनाया जा सकता है।
थॉमस डिके

3

fileएक विकल्प है --mime-encodingजो एक फ़ाइल के एन्कोडिंग का पता लगाने का प्रयास करता है।

 $file --mime-encoding Documents/poster2.pdf 
Documents/poster2.pdf: binary
 $file --mime-encoding projects/linux/history-torvalds/Makefile 
projects/linux/history-torvalds/Makefile: us-ascii
 $file --mime-encoding graphe.tex 
Dgraphe.tex: us-ascii
 $file --mime-encoding software.tex 
software.tex: utf-8

आप उपयोग कर सकते हैं file --mime-encoding | grep binary पता लगाने के लिए कि क्या कोई फाइल बाइनरी फाइल है। यह मज़बूती से काम करता है, हालांकि यह एक लंबे पाठ फ़ाइल में एकल अमान्य वर्ण द्वारा भ्रमित हो सकता है।

उदाहरण के लिए, मैं catअनजाने में एक बाइनरी फ़ाइल खोलकर अपने टर्मिनल को बर्बाद करने से बचने के लिए निम्न शेल स्क्रिप्ट का उपनाम देता हूं :

#! /bin/sh -

[ ! -t 1 ] && exec /bin/cat "$@"
for i
do
    if file --mime-encoding -- "$i" | grep -q binary
    then
        hexdump -C -- "$i"
    else
        /bin/cat -- "$i"
    fi
done

3

श्रेणियाँ मनमानी हैं। एक वर्गीकरण बनाने का उत्तर देने से पहले, आपको एक (सख्त) परिभाषा की आवश्यकता है। एक परिभाषा के लिए, आपको एक उद्देश्य की आवश्यकता है

तो, आप उस वर्गीकरण के साथ क्या करना चाहते हैं?

  • यदि आप एफ़टीपी में एएससीआई / बाइनरी का चयन करना चाहते हैं, तो यह महत्वपूर्ण है कि बाइनरी फ़ाइल को एससीआई (या यह भ्रष्ट हो जाएगा) के रूप में स्थानांतरित न करें। यदि फाइल सादा पाठ, HTML, rtf और कुछ अन्य है तो आप शुलड टेस्ट करते हैं। लेकिन संदेह में, बाइनरी का चयन करें। और शायद आप यह भी परखना चाहते हैं कि फ़ाइल में केवल 0x0A, 0x0D, और 0x20-0x7F जैसे उपसमूह हैं।
  • यदि आप फ़ाइल को कुछ प्रोटोकॉल (POP3, SMTP) में स्थानांतरित करना चाहते हैं, तो आपको यह चुनने के लिए परीक्षण करना होगा कि क्या बेस 64 या सिर्फ सादे में एन्कोड किया गया है। इस स्थिति में, आपको असमर्थित वर्ण होने पर परीक्षण करना चाहिए।
  • किसी भी अन्य मामले ... कोई अन्य परिभाषा हो सकती है।

3
perl -e'chomp(my$f=<>);print "binary$/" if -B $f;print "text$/" if -T _'

करूंगा। के लिए प्रलेखन -Bऔर-T देखें (स्ट्रिंग के लिए उस पृष्ठ में खोजें The -T and -B switches work as follows)।


perl -le 'print -B $ARGV[0] ? "binary" : "text"' --स्पष्ट हो सकता है। या यहां तक ​​किperl -le 'print -B $_ ? "binary" : "text", @ARGV > 1 ? "\t$_" : "" for @ARGV' --
jrw32982

1

मैंने https://github.com/audreyr/binaryornot में योगदान दिया है, इसमें कमांड लाइन आवरण (अभी तक) नहीं है, लेकिन यह एक साधारण पायथन लाइब्रेरी है जो सीएलआई से भी कॉल करने के लिए काफी आसान है। यह निर्धारित करने के लिए एक काफी कुशल हेयुरिस्टिक का उपयोग करता है कि क्या कोई फ़ाइल पाठ या बाइनरी है।


1

अब मैं यह जवाब थोड़ा पुराना है, लेकिन मुझे लगता है कि मेरे दोस्त ने मुझे ऐसा करने के लिए एक महान "हैक" सिखाया।

आप diffकमांड का उपयोग करते हैं और टेस्ट फाइल के खिलाफ अपनी फाइल की जांच करते हैं:

$ diff filetocheck testfile.txt

अब अगर filetocheckएक बाइनरी फ़ाइल है, तो आउटपुट होगा:

Binary files filetocheck and testfile.txt differ

इस तरह आप diffकमांड का लाभ उठा सकते हैं और उदाहरण के लिए एक फंक्शन लिखते हैं जो एक स्क्रिप्ट में चेक करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.