ইউনিক্স / লিনাক্সে দুটি ফাইলের একই বিষয়বস্তু রয়েছে কিনা তা বলার দ্রুততম উপায়?


231

আমার একটি শেল স্ক্রিপ্ট রয়েছে যাতে দুটি ফাইলের একই ডেটা রয়েছে কি না তা যাচাই করতে হবে। আমি অনেকগুলি ফাইলের জন্য এটি করি এবং আমার স্ক্রিপ্টে diffকমান্ডটি কার্যকারিতা বাধা বলে মনে হচ্ছে।

লাইনটি এখানে:

diff -q $dst $new > /dev/null

if ($status) then ...

ফাইলগুলির তুলনা করার আরও দ্রুত কোনও উপায় হতে পারে, ডিফল্ট পরিবর্তে একটি কাস্টম অ্যালগরিদম হতে পারে diff?


10
এটি সত্যিই নিটপিকিং, তবে আপনি দুটি ফাইল একই কিনা তা জিজ্ঞাসা করছেন না, আপনি দুটি ফাইলের অভিন্ন সামগ্রী রয়েছে কিনা তা জিজ্ঞাসা করছেন না। একই ফাইলগুলিতে অভিন্ন ইনোড থাকে (এবং একই ডিভাইস)।
জ্যানো

1
গৃহীত উত্তর মতো মধ্যে পরিমাপ এই উত্তর মধ্যে কোনো উল্লেখযোগ্য পার্থক্য স্বীকার করে না diffএবং cmp
vii

উত্তর:


388

আমি বিশ্বাস করি cmpপ্রথম বাইট পার্থক্যে থামবে:

cmp --silent $old $new || echo "files are different"

1
আমি কীভাবে কেবল একটির চেয়ে বেশি কমান্ড যুক্ত করতে পারি? আমি একটি ফাইল অনুলিপি এবং রোবট করতে চান।
feedc0de

9
cmp -s $old $newকাজ করে। -sসংক্ষিপ্ত--silent
রোহ্মার

7
একটি গতি বৃদ্ধি হিসাবে, আপনার লিখিত সামগ্রীটি তুলনা করার আগে ফাইল আকারগুলি সমান কিনা তা পরীক্ষা করা উচিত। সিএমপি এটি করে কিনা কেউ জানে?
বিউভুলফনোড 42

3
একাধিক কমান্ড চালানোর জন্য, আপনি বন্ধনী ব্যবহার করতে পারেন: cmp -s পুরানো নতুন || {প্রতিধ্বনিত হয় না; প্রতিধ্বনি প্রতিধ্বনি একই; }
আনফা

6
@ বিউওউলফনোড 42 হ্যাঁ, যে কোনও শালীন প্রয়োগটি cmpপ্রথমে ফাইলের আকার চেক করবে। এখানে জিএনইউ সংস্করণটি রয়েছে, যদি আপনি এটির সাথে যুক্ত অতিরিক্ত অপ্টিমাইজেশন দেখতে চান: git.savannah.gnu.org/cgit/diffutils.git/tree/src/cmp.c
রায়ান গ্রাহাম

53

আমি পছন্দ করি @ অ্যালেক্স হাওয়ানস্কি এর জন্য 'সিএমপি - সাইলেন্ট' ব্যবহার করেছেন। তবে আমি ব্যবহার করি তাই ইতিবাচক এবং নেতিবাচক উভয় প্রতিক্রিয়া:

cmp --silent file1 file2 && echo '### SUCCESS: Files Are Identical! ###' || echo '### WARNING: Files Are Different! ###'

আমি এটির পরে টার্মিনালে বা ssh দিয়ে এটি চালাতে পারি ধ্রুবক ফাইলের বিরুদ্ধে ফাইলগুলি পরীক্ষা করতে।


16
যদি আপনার echo successকমান্ড (বা অন্য কোনও আদেশ আপনি এর স্থলে রাখেন) ব্যর্থ হয়, আপনার "নেতিবাচক প্রতিক্রিয়া" কমান্ডটি চালানো হবে। আপনার "যদি-তারপর-অন্যথায়-ফাই" নির্মাণ করা উচিত। উদাহরণস্বরূপ, এই সাধারণ উদাহরণটি পছন্দ করুন
ওয়াইল্ডকার্ড

18

আপনি উভয় ফাইলের সামগ্রীর হ্যাশ পাবেন না কেন?

এই স্ক্রিপ্টটি ব্যবহার করে দেখুন, উদাহরণ হিসেবে স্ক্রিপ্ট.শ এর জন্য কল করুন এবং তারপরে এটি চালান: স্ক্রিপ্ট.শ file1.txt file2.txt

#!/bin/bash

file1=`md5 $1`
file2=`md5 $2`

if [ "$file1" = "$file2" ]
then
    echo "Files have the same content"
else
    echo "Files have NOT the same content"
fi

2
@THISUSERNEEDSHELP কারণ হ্যাশ অ্যালগোরিদমগুলি রয়েছে না এক এক করে। এগুলি এমনভাবে তৈরি করা হয়েছে যে হ্যাশিংয়ের স্থানটি বড় এবং বিভিন্ন ইনপুটগুলিতে বিভিন্ন হ্যাশ উত্পাদন করার উচ্চ সম্ভাবনা থাকে। বাস্তবতা যদিও হ্যাশ স্পেস সীমাবদ্ধ, যখন হ্যাশের সম্ভাব্য ফাইলগুলির পরিসীমা নয় - শেষ পর্যন্ত আপনার সংঘর্ষ হবে। ক্রিপ্টোলজিতে একে জন্মদিনের আক্রমণ বলে
হবে

5
@ ইহ, এটি কার্যকরভাবে কাজ করার গ্যারান্টিযুক্ত। এটা মতভেদ কাজ করছে না হয়, গাণিতিকভাবে, ভাষী প্রায় 1/(2^511)। যদি না আপনি উদ্বেগজনকভাবে কোনও সংঘর্ষ তৈরি করার চেষ্টা করছেন এমন কেউ সম্পর্কে উদ্বিগ্ন হন তবে মিথ্যা ধনাত্মক উত্পাদন করার পদ্ধতিটি সত্যই গুরুতর উদ্বেগ নয়। cmpযদিও এখনও আরও দক্ষ, যেহেতু ফাইলগুলি মেলে না এমন ক্ষেত্রে এটি পুরো ফাইলটি পড়তে হবে না।
আজেদী 32

12
ওপি দ্রুততম পদ্ধতির জন্য জিজ্ঞাসা করেছিল ... পুরো ফাইলটি হ্যাশ করার চেয়ে প্রথম অ-ম্যাচিং বিট (সিএমপি ব্যবহার করে) দ্রুত হবে না (বিশেষত ফাইলগুলি বড় হলে)?
কোজেডএম 0 কে 13

3
আপনি অনেক তুলনা করতে একটি করছেন যদি md5 সেরা। আপনি এমডি 5 হ্যাশ প্রতিটি ফাইলের বিপরীতে একটি বৈশিষ্ট্য হিসাবে বা একটি ডাটাবেসে সংরক্ষণ করতে পারেন। যদি কোনও নতুন ফাইল উপস্থিত হয় এবং আপনার যদি একই সিস্টেম ফাইল ফাইলের কোথাও উপস্থিত থাকে কিনা তা পরীক্ষা করে দেখতে হয় তবে আপনারা যা করেন তা হ'ল নতুন ফাইলের হ্যাশ গণনা করা এবং পূর্ববর্তী সমস্তগুলির বিরুদ্ধে পরীক্ষা করা। নিশ্চিত যে গিট কোনও কমিটের সময় ফাইলের পরিবর্তনগুলি পরীক্ষা করার জন্য হ্যাশিং ব্যবহার করে তবে তারা SHA1 ব্যবহার করে।
জিমহফ

3
@ বিউওলফনোড 42 এই কারণেই আমি আমার মন্তব্যে পূর্ববর্তী বলেছিলাম "যদি না আপনি ইচ্ছাকৃতভাবে সংঘর্ষ তৈরির চেষ্টা করছেন এমন কাউকে নিয়ে উদ্বিগ্ন হন না"
আজেদী 32

5

কারণ আমি স্তন্যপান করি এবং পর্যাপ্ত খ্যাতি পয়েন্ট না থাকায় আমি এই মন্তব্যটি কোনও মন্তব্য হিসাবে যুক্ত করতে পারি না।

তবে, আপনি যদি cmpকমান্ডটি ব্যবহার করতে যাচ্ছেন (এবং ভার্বোস হওয়ার প্রয়োজন নেই / চান না) আপনি কেবল প্রস্থান স্থিতিটি ধরে নিতে পারেন। প্রতি cmpমানুষ পৃষ্ঠা:

যদি কোনও ফাইল '-' বা অনুপস্থিত থাকে তবে স্ট্যান্ডার্ড ইনপুটটি পড়ুন। প্রস্থান স্থিতি 0 হয় যদি ইনপুট একই হয়, 1 পৃথক হলে 2, সমস্যা হলে।

সুতরাং, আপনি যেমন কিছু করতে পারেন:

STATUS="$(cmp --silent $FILE1 $FILE2; echo $?)"  # "$?" gives exit status for each comparison

if [[$STATUS -ne 0]]; then  # if status isn't equal to 0, then execute code
    DO A COMMAND ON $FILE1
else
    DO SOMETHING ELSE
fi

হ্যাঁ, তবে এটি আসলে আরও জটিল পদ্ধতি cmp --silent $FILE1 $FILE2 ; if [ "$?" == "1" ]; then echo "files differ"; fiযা ঘুরে দেখার আরও জটিল পদ্ধতি cmp --silent $FILE1 $FILE2 || echo "files differ"কারণ আপনি সরাসরি অভিব্যক্তিতে আদেশটি ব্যবহার করতে পারেন। এটি বিকল্প $?। ফলস্বরূপ কমান্ডের বিদ্যমান অবস্থার তুলনা করা হবে। এবং অন্য উত্তর কি এটি। BTW। যদি কারও সাথে লড়াই করা হয় তবে --silentএটি সর্বত্র সমর্থিত নয় (ব্যস্তবক্স)। ব্যবহার-s
পাপো

4

পৃথক নয় এমন ফাইলগুলির জন্য, যে কোনও পদ্ধতিতে উভয় ফাইল সম্পূর্ণরূপে পড়া দরকার, এমনকি পাঠ আগেও ছিল।

এর বিকল্প নেই। সুতরাং সময়ে কোনও সময়ে হ্যাশ বা চেকসাম তৈরি করতে পুরো ফাইলটি পড়া দরকার। বড় ফাইলগুলি সময় নেয়।

একটি বড় ফাইল পড়ার চেয়ে ফাইল মেটাডেটা পুনরুদ্ধার অনেক দ্রুত।

সুতরাং, ফাইলগুলি আলাদা কিনা তা প্রতিষ্ঠিত করতে আপনি কোনও ফাইল মেটাডেটা ব্যবহার করতে পারেন? ফাইলের আকার ? বা এমনকি ফাইলের কমান্ডের ফলাফল যা কেবলমাত্র ফাইলের একটি ছোট্ট অংশটি পড়ে?

ফাইল আকার উদাহরণ কোড টুকরা:

  ls -l $1 $2 | 
  awk 'NR==1{a=$5} NR==2{b=$5} 
       END{val=(a==b)?0 :1; exit( val) }'

[ $? -eq 0 ] && echo 'same' || echo 'different'  

যদি ফাইলগুলি একই আকারের হয় তবে আপনি সম্পূর্ণ ফাইল রিডের সাথে আটকে আছেন।


1
ls -nব্যবহারকারী বা গোষ্ঠীর নামের শ্বেত স্থান থাকলে সমস্যাগুলি এড়াতে ব্যবহার করুন ।
ট্রাইসেস

2

Cksum কমান্ড ব্যবহার করার চেষ্টা করুন:

chk1=`cksum <file1> | awk -F" " '{print $1}'`
chk2=`cksum <file2> | awk -F" " '{print $1}'`

if [ $chk1 -eq $chk2 ]
then
  echo "File is identical"
else
  echo "File is not identical"
fi

Cksum কমান্ড একটি ফাইলের বাইট গণনা আউটপুট করবে। 'ম্যান স্যাক্সম' দেখুন।


2
যে খুব আমার প্রথম চিন্তা ছিল। তবে, হ্যাশগুলি বোঝায় যে আপনি যদি একই ফাইলটিকে অনেকবার তুলনা করতে চান, কারণ হ্যাশটি কেবল একবারেই গণনা করা হয়। যদি আপনি এটির সাথে কেবল একবার তুলনা করেন, তবে md5পুরো ফাইলটি যাইহোক পড়ুন, সুতরাং cmp, প্রথম পার্থক্যে থামানো, দ্রুততর হবে।
ফ্রান্সেস্কো দন্ডি

0

রাস্পবেরি পাই 3 বি + (আমি একটি ওভারলে ফাইল সিস্টেম ব্যবহার করছি এবং পর্যায়ক্রমে সিঙ্ক করার দরকার আছে) দিয়ে কিছু পরীক্ষা নিরীক্ষা করে আমি ডিফ-কিউ এবং সিএমপি-এস এর জন্য আমার নিজের তুলনা চালিয়েছি; মনে রাখবেন যে এটি / dev / shm এর ভিতরে থেকে একটি লগ, সুতরাং ডিস্ক অ্যাক্সেসের গতি একটি ইস্যু নয়:

[root@mypi shm]# dd if=/dev/urandom of=test.file bs=1M count=100 ; time diff -q test.file test.copy && echo diff true || echo diff false ; time cmp -s test.file test.copy && echo cmp true || echo cmp false ; cp -a test.file test.copy ; time diff -q test.file test.copy && echo diff true || echo diff false; time cmp -s test.file test.copy && echo cmp true || echo cmp false
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 6.2564 s, 16.8 MB/s
Files test.file and test.copy differ

real    0m0.008s
user    0m0.008s
sys     0m0.000s
diff false

real    0m0.009s
user    0m0.007s
sys     0m0.001s
cmp false
cp: overwrite âtest.copyâ? y

real    0m0.966s
user    0m0.447s
sys     0m0.518s
diff true

real    0m0.785s
user    0m0.211s
sys     0m0.573s
cmp true
[root@mypi shm]# pico /root/rwbscripts/utils/squish.sh

আমি কয়েকবার দৌড়েছি। আমি যে পরীক্ষামূলক বাক্সটি ব্যবহার করছিলাম সেটিতে সিএমপি-গুলি ধারাবাহিকভাবে কিছুটা ছোট ছিল। সুতরাং আপনি যদি দুটি ফাইলের মধ্যে কাজ করতে সিএমপি-গুলি ব্যবহার করতে চান ....

identical (){
  echo "$1" and "$2" are the same.
  echo This is a function, you can put whatever you want in here.
}
different () {
  echo "$1" and "$2" are different.
  echo This is a function, you can put whatever you want in here, too.
}
cmp -s "$FILEA" "$FILEB" && identical "$FILEA" "$FILEB" || different "$FILEA" "$FILEB"
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.