लिनक्स टर्मिनल में दो फाइलों की तुलना


168

"A.txt" और "b.txt" नामक दो फाइलें हैं, दोनों में शब्दों की एक सूची है। अब मैं जाँच करने के लिए जो शब्दों में अतिरिक्त कर रहे हैं चाहते हैं "a.txt" और में नहीं हैं "b.txt"

मुझे एक कुशल एल्गोरिथ्म की आवश्यकता है क्योंकि मुझे दो शब्दकोशों की तुलना करने की आवश्यकता है।


27
diff a.txt b.txtकाफी नहीं है?
थैंक्सफॉरइलिश

क्या प्रत्येक फ़ाइल में शब्द कई बार हो सकते हैं? क्या आप फ़ाइलों को सॉर्ट कर सकते हैं?
बेसिल स्टैरनेवविच

मुझे केवल उन शब्दों की आवश्यकता है जो "b.txt" में मौजूद नहीं हैं और a.txt में मौजूद हैं
अली इमरान

जवाबों:


343

यदि आपने विम स्थापित किया है, तो यह कोशिश करें:

vimdiff file1 file2

या

vim -d file1 file2

आपको यह शानदार लगेगा।यहां छवि विवरण दर्ज करें


9
निश्चित रूप से कमाल, डिजाइन में अच्छा और अंतर जानने में आसान। ओमिगॉड
ज़ेन

1
आपका उत्तर भयानक है, लेकिन मेरे शिक्षक को मुझे किसी भी पुस्तकालय समारोह का उपयोग नहीं करने की आवश्यकता है: पी
अली इमरान

1
क्या शानदार उपकरण है! यह बेहद मददगार है।
user1205577

1
उन रंगों के क्या मायने हैं?
जिंजिमेंटस

1
रंगीन कोड का मतलब है कि वे दो फाइलों में भिन्न हैं। @zygimantus
फेंगिया ली

73

उन्हें क्रमबद्ध करें और उपयोग करें comm:

comm -23 <(sort a.txt) <(sort b.txt)

commतुलना (क्रमबद्ध) इनपुट फ़ाइलों और डिफ़ॉल्ट रूप से तीन कॉलम आउटपुट: लाइनों जो एक के लिए अद्वितीय हैं, लाइनों जो बी के लिए अद्वितीय हैं, और लाइनें जो दोनों में मौजूद हैं। निर्दिष्ट करके -1, -2और / या -3आप संबंधित आउटपुट को दबा सकते हैं। इसलिए comm -23 a bकेवल उन प्रविष्टियों को सूचीबद्ध करता है जो अद्वितीय हैं। मैं <(...)सिंटैक्स का उपयोग फ़्लाई पर फ़ाइलों को सॉर्ट करने के लिए करता हूं , अगर वे पहले से ही सॉर्ट किए जाते हैं तो आपको इसकी आवश्यकता नहीं है।


मैंने केवल grep कमांड का उपयोग करके अपना जवाब जोड़ा है, कृपया मुझे बताएं कि क्या यह अधिक कुशल है?
अली इमरान

3
@AliImran, commअधिक कुशल है क्योंकि यह पूरी फ़ाइल को मेमोरी में स्टोर किए बिना एक ही रन में काम करता है। चूंकि आप उन शब्दकोशों का उपयोग कर रहे हैं जो पहले से ही क्रमबद्ध हैं, इसलिए आपको sortउनकी आवश्यकता भी नहीं है। grep -f file1 file2दूसरी ओर का उपयोग पूरे file1मेमोरी में लोड होगा और file2उन सभी प्रविष्टियों के साथ प्रत्येक पंक्ति की तुलना करेगा , जो बहुत कम कुशल है। यह ज्यादातर छोटे, अनसोल्ड के लिए उपयोगी है -f file1
एंडर्स जोहानसन

1
"कॉम" कमांड साझा करने के लिए @AndersJohansson को धन्यवाद। निफ्टी वास्तव में। मुझे अक्सर फ़ाइलों के बीच बाहरी जुड़ाव करना पड़ता है और यह चाल करता है।
ब्लिसप्र

नई लाइन के चरित्र पर ध्यान दें ... मैंने अभी पाया कि \nतुलना करने के लिए भी शामिल किया जाएगा।
बिन


28

आप diffदो फ़ाइलों की तुलना करने के लिए लिनक्स में टूल का उपयोग कर सकते हैं । आप उपयोग कर सकते हैं --changed-समूह-प्रारूप और --unchanged-समूह-प्रारूप फिल्टर आवश्यक डेटा के लिए विकल्प।

निम्नलिखित तीन विकल्प प्रत्येक विकल्प के लिए संबंधित समूह का चयन करने के लिए उपयोग कर सकते हैं:

  • '% <' को FILE1 से लाइनें मिलती हैं

  • '%>' को FILE2 से लाइनें मिलती हैं

  • दोनों फाइलों से लाइनें हटाने के लिए '' (खाली स्ट्रिंग)।

जैसे: diff -changed-group-format = "% <" --unchanged-group-format = "" file1.txt file2.txt

[root@vmoracle11 tmp]# cat file1.txt 
test one
test two
test three
test four
test eight
[root@vmoracle11 tmp]# cat file2.txt 
test one
test three
test nine
[root@vmoracle11 tmp]# diff --changed-group-format='%<' --unchanged-group-format='' file1.txt file2.txt 
test two
test four
test eight

27

यदि आप अलग-अलग आउटपुट शैली पसंद करते हैं git diff, तो आप इसका उपयोग --no-indexझंडे के साथ उन फ़ाइलों की तुलना करने के लिए कर सकते हैं, जो एक रिपॉजिटरी में नहीं हैं:

git diff --no-index a.txt b.txt

प्रत्येक में लगभग 200k फ़ाइल नाम स्ट्रिंग के साथ कुछ फ़ाइलों का उपयोग करते हुए, मैंने बेंचमार्क किया (अंतर्निहित timeकमांड के साथ) इस दृष्टिकोण बनाम कुछ अन्य उत्तर यहां दिए गए हैं:

git diff --no-index a.txt b.txt
# ~1.2s

comm -23 <(sort a.txt) <(sort b.txt)
# ~0.2s

diff a.txt b.txt
# ~2.6s

sdiff a.txt b.txt
# ~2.7s

vimdiff a.txt b.txt
# ~3.2s

commअब तक सबसे तेज़ git diff --no-indexप्रतीत होता है , जबकि यह विधा-शैली के आउटपुट के लिए सबसे तेज़ तरीका है।


अपडेट 2018-03-25 आप वास्तव में --no-indexध्वज को छोड़ सकते हैं जब तक कि आप गिट रिपॉजिटरी के अंदर नहीं होते हैं और उस रिपॉजिटरी के भीतर अनटैक की गई फ़ाइलों की तुलना करना चाहते हैं। से आदमी पृष्ठों :

यह फॉर्म फाइलसिस्टम पर दिए गए दो रास्तों की तुलना करना है। Git द्वारा नियंत्रित वर्किंग ट्री में कमांड चलाने पर आप -no- इंडेक्स ऑप्शन को छोड़ सकते हैं और वर्किंग ट्री के बाहर कम से कम एक पाथ पॉइंट्स या जब गिट द्वारा नियंत्रित वर्किंग ट्री के बाहर कमांड चला रहे हों।


9

आप यह भी उपयोग कर सकते हैं: colordiff : रंगों के साथ अंतर के आउटपुट को प्रदर्शित करता है।

Vimdiff के बारे में : यह आपको SSH के माध्यम से फाइलों की तुलना करने की अनुमति देता है, उदाहरण के लिए:

vimdiff /var/log/secure scp://192.168.1.25/var/log/secure

इससे निकाला गया: http://www.sysadmit.com/2016/05/linux-diferencias-entre-dos-archivos.html



4

उपयोग comm -13 (आवश्यक फ़ाइलों की आवश्यकता होती है) :

$ cat file1
one
two
three

$ cat file2
one
two
three
four

$ comm -13 <(sort file1) <(sort file2)
four

1

यहाँ इसके लिए मेरा समाधान है:

mkdir temp
mkdir results
cp /usr/share/dict/american-english ~/temp/american-english-dictionary
cp /usr/share/dict/british-english ~/temp/british-english-dictionary
cat ~/temp/american-english-dictionary | wc -l > ~/results/count-american-english-dictionary
cat ~/temp/british-english-dictionary | wc -l > ~/results/count-british-english-dictionary
grep -Fxf ~/temp/american-english-dictionary ~/temp/british-english-dictionary > ~/results/common-english
grep -Fxvf ~/results/common-english ~/temp/american-english-dictionary > ~/results/unique-american-english
grep -Fxvf ~/results/common-english ~/temp/british-english-dictionary > ~/results/unique-british-english

2
क्या आपने किसी अन्य समाधान की कोशिश की? क्या इनमें से कोई एक समाधान आपके लिए उपयोगी था? आपका प्रश्न कई उपयोगकर्ताओं में आकर्षित करने के लिए पर्याप्त सामान्य है, लेकिन आपका उत्तर मेरे स्वाद के लिए अधिक विशिष्ट है ... मेरे विशेष मामले के sdiff -s file1 file2लिए उपयोगी था।
मेटाफैनियल

@Metafaniel मेरा समाधान sdiff कमांड का उपयोग नहीं करता है। यह समस्या को हल करने के लिए केवल कमांड में निर्मित लिनक्स का उपयोग करता है।
अली इमरान

-1

इसके लिए जाग का उपयोग करना। परीक्षण फ़ाइलें:

$ cat a.txt
one
two
three
four
four
$ cat b.txt
three
two
one

जाग:

$ awk '
NR==FNR {                    # process b.txt  or the first file
    seen[$0]                 # hash words to hash seen
    next                     # next word in b.txt
}                            # process a.txt  or all files after the first
!($0 in seen)' b.txt a.txt   # if word is not hashed to seen, output it

डुप्लिकेट आउटपुट हैं:

four
four

डुप्लिकेट से बचने के लिए, axt में प्रत्येक नए मिले हुए शब्द को seenहैश में जोड़ें:

$ awk '
NR==FNR {
    seen[$0]
    next
}
!($0 in seen) {              # if word is not hashed to seen
    seen[$0]                 # hash unseen a.txt words to seen to avoid duplicates 
    print                    # and output it
}' b.txt a.txt

आउटपुट:

four

यदि शब्द सूचियाँ अल्पविराम से अलग हैं, जैसे:

$ cat a.txt
four,four,three,three,two,one
five,six
$ cat b.txt
one,two,three

आपको कुछ अतिरिक्त अंतराल ( forलूप) करने होंगे:

awk -F, '                    # comma-separated input
NR==FNR {
    for(i=1;i<=NF;i++)       # loop all comma-separated fields
        seen[$i]
    next
}
{
    for(i=1;i<=NF;i++)
        if(!($i in seen)) {
             seen[$i]        # this time we buffer output (below):
             buffer=buffer (buffer==""?"":",") $i
        }
    if(buffer!="") {         # output unempty buffers after each record in a.txt
        print buffer
        buffer=""
    }
}' b.txt a.txt

इस बार आउटपुट:

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