फ़ाइल के अंत में न्यूलाइन के लिए जाँच से अलग रोकें


21

मेरे पास दो बड़े पेड़ हैं, जिनकी मैं तुलना करना चाहता हूं। पेड़ की कुछ फाइलें सिर्फ इसलिए अलग हो जाती हैं क्योंकि एक में नई लाइन होती है, और दूसरी फाइल में इस नई लाइन का अभाव होता है। मैं इस तथ्य को नजरअंदाज करना चाहता हूं। मैंने diffइस तरह से कॉल करने की कोशिश की है :

diff --ignore-all-space -r <dir1> <dir2>

और यह काम कर रहा है। मेरी समस्या यह है कि यह अन्य अंतरों (स्थान-संबंधी) को भी अनदेखा करता है, जो महत्वपूर्ण हो सकता है।

सारांश में: मैं सिर्फ EOF पर न्यू लाइन अनदेखा करना चाहते। क्या यह संभव है diff?

जवाबों:


17

आपको मूल रूप से दो फ़ाइलों की तुलना करने की आवश्यकता है, सशर्त रूप से अनुगामी बाइट की अनदेखी करना। ऐसा करने के लिए कोई 'भिन्न' विकल्प नहीं है - लेकिन कई तरीके हैं जिनसे यह किया जा सकता है (उदाहरण के लिए, हेक्स अंतर भी ध्यान में आता है।)

'भिन्न' का उपयोग करने के लिए, आपको मूल रूप से उन फ़ाइलों को संशोधित करना होगा जो एक फ़ाइल के अंत में नई रेखा को याद कर रहे हैं, और फिर तुलना करें। आप संशोधित फ़ाइलों के साथ एक अस्थायी निर्देशिका बना सकते हैं, या थोड़ी सी स्क्रिप्टिंग के साथ इसे मेमोरी में किया जा सकता है। (जैसा कि पसंद किया जाता है, वरीयता, फ़ाइल का आकार, फ़ाइलों की संख्या ...) पर निर्भर करता है

उदाहरण के लिए, निम्नलिखित एक फ़ाइल की सामग्री को संशोधित करेगा (एक sed -iजगह में संशोधन करने के लिए उपयोग , यह सिर्फ प्रिंट करता है) यदि कोई लापता है (या पहले से ही एक नई पंक्ति है तो फ़ाइल को अपरिवर्तित छोड़ दें):

sed -e '$a\'  file1.txt

और सिर्फ़ 'अलग' सिंटैक्स की समीक्षा करने के लिए (सही मायने में वापसी का मतलब है कि वे समान हैं, झूठे का मतलब अलग है):

$ diff a/file1.txt   b/file1.txt  \
      && echo '** are same' || echo '** are different'
2c2
< eof
---
> eof
\ No newline at end of file
** are different

सत्यापित करें कि केवल व्हाट्सएप अलग है:

$ diff --ignore-all-space  a/file1.txt   b/file1.txt \
     && echo '** are same' || echo '** are different'
** are same

बैश में, हम 'सेड' का उपयोग फाइल कंटेंट में फेरबदल करने के लिए कर सकते हैं क्योंकि यह 'डिफर्ड' (मूल फाइल जो बिना लाइसेंस के छोड़ दिया गया है):

$ diff <(sed -e '$a\' a/file1.txt) <(sed -e '$a\' b/file1.txt) \
     && echo '** are same' || echo '** are different'
** are same

अब आपको केवल इतना करना है कि diff -rनिर्देशिकाओं की पुनरावृत्ति की तुलना करें। यदि निर्देशिकाओं की तुलना aऔर b, तो सभी फ़ाइलों के लिए a(जैसे, a/dir1/dir2/file.txt) फ़ाइल में पथ प्राप्त करें b(जैसे, b/dir1/dir2/file.txt) और तुलना करें:

$ for f in $( find a -type f  )
> do
>    diff <(sed -e '$a\' $f) <(sed -e '$a\' b/${f#*/})
> done

थोड़ा और अधिक वर्बोज़ संस्करण:

$ for f in $( find a -type f  )
> do
>   f1=$f
>   f2=b/${f#*/}
>   echo "compare: $f1 $f2"
>   diff <(sed -e '$a\' $f1) <(sed -e '$a\' $f2) \
>       && echo '** are same' || echo '** are different'
> done && echo '** all are same' || echo '** all are different'
compare: a/file1.txt b/file1.txt
** are same
compare: a/file2.txt b/file2.txt
** are same
** all are same

क्या आप बता सकते हैं कि sed -e '$a\'वास्तव में क्या करता है? thx
törzsmókus

चलाने sedके लिए, निम्न (दी -e) स्क्रिप्ट / अभिव्यक्ति है, जो फ़ाइल (के अंत से मेल खाता है $), और "संलग्न" कार्रवाई (एक \) करते हैं, लेकिन वास्तव में किसी भी पाठ को निर्दिष्ट नहीं करते (के बाद `\` कुछ भी नहीं), जो अभी भी फ़ाइल के अंत में एक EOF / newline जोड़ने जा रहा है (केवल अगर यह गायब है)।
माइकल

धन्यवाद। मैंने a\ अभी तक नहीं देखा ।
törzsmókus

1

मैंने प्रत्येक फाइल में एक नई पंक्ति जोड़कर और अंतर (विकल्प -B) में रिक्त लाइनों को अनदेखा करके समस्या को हल किया । यह समाधान आपके उपयोग के मामले के लिए उपयुक्त नहीं हो सकता है लेकिन यह दूसरों की मदद कर सकता है:

echo >> $FILE1 
echo >> $FILE2
diff -B $FILE1 FILE2 

0

पाइप के उत्पादन में diffएक करने के लिए grepआदेश है कि संदेश आप को देखने के लिए नहीं करना चाहती चला जाता है।


अच्छा नही। diff -r परिणाम के साथ मौजूद है! = 0 अगर मैं --ignore-all-space नहीं जोड़ता। स्पष्ट होने के लिए: मैं ईओएफ पर नए सिरे से उपेक्षा करना चाहता हूं, और केवल ईओएफ में। और मैं चाहता हूं कि यह एक परिणाम की रिपोर्ट करे जो इस मानदंड से मेल खाता है। यही है, अगर पेड़ में फाइलें केवल
ईओएफ पर नईलाइन

0

बस एक अलग दृष्टिकोण के बारे में सोचा, जो बड़ी फ़ाइलों के लिए काम करेगा (और अभी भी मूल फ़ाइलों की प्रतिलिपि नहीं बनाता है या संशोधित नहीं करता है)। आपको अभी भी पुनरावर्ती निर्देशिका ट्रैवर्सल का अनुकरण करना होगा (और ऐसा करने के कई तरीके हैं), लेकिन यह उदाहरण 'sed' का उपयोग नहीं करता है, बल्कि केवल दो फाइलों की तुलना करता है, अंतिम बाइट को छोड़कर, उपयोग करते हुए cmp, जैसे,

$ cmp  a/file1.txt  b/file1.txt  && echo '** are same' || echo '** are different'
cmp: EOF on b/file1.txt
** are different

$ du -b a/file1.txt  b/file1.txt 
13  a/file1.txt
12  b/file1.txt

$ cmp  -n 12 a/file1.txt  b/file1.txt  && echo '** are same' || echo '** are different'
** are same

अभी भी निर्देशिका में सभी फ़ाइलों पर लूप, और दो फ़ाइलों के लिए a / file.txt और b / file.txt, बड़ी फ़ाइल आकार की गणना करें, और एक को घटाएं, फिर cmpबाइट को अलग करें ( ) बाइट्स की संख्या का उपयोग करके (में भी दे घुमा के):

(( bytes = $(du -b a/file.txt  b/file.txt  | sort -nr | head -1  | cut -f1) - 1 ))
cmp -n $bytes a/file.txt b/file.txt

फ़ाइलों पर लूपिंग का उपयोग अन्य उत्तर के रूप में ही होगा sedऔर diff


0

उत्तर सीधा है।
अनुपलब्ध न्यूलाइन के बारे में संदेश आउटपुट स्ट्रीम में नहीं diffबल्कि त्रुटि स्ट्रीम में है। तो इसे निर्वाण के लिए झुकें और आप अच्छे के लिए किए गए हैं

diff -rqEeB fileA fileB 2> /dev/null

अंतर एक मान लौटाता है! = 0 यदि यह अंतर पाता है और मैं उस मूल्य की जांच करना चाहता हूं। / Dev / null को पुनर्निर्देशित करने से उस अंतर के बारे में कोई फर्क नहीं पड़ता, इसलिए लौटाया गया मान =! 0 है, जो मुझे नहीं चाहिए। मैं दो फाइलों के बराबर विचार करना चाहता हूं यदि एकमात्र अंतर अंतिम नई रेखा है
खतरे का समय

-1

वहाँ एक झंडा --strip-trailing-crहै, जो कि आप के लिए कहा है कि वास्तव में करते हैं


-1। क्या आपने यह कोशिश की है? यह ईओएफ के ठीक पहले के अतिरिक्त व्यवहार करता /r/nहै /nऔर इसका कोई लेना-देना नहीं है /n
कामिल मैकियोरोस्की

मैंने यह कोशिश की है, और इसे अलग-अलग डॉस / यूनिक्स न्यूलाइन के साथ फाइल करने के लिए इस्तेमाल किया है ... क्या यह सही नहीं है?
०man

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