مقایسهی فایلها یکی از کارهای رایج در مدیریت سیستم، برنامهنویسی و تحلیل دادههاست. ابزارهای diff و comm دو رویکرد متفاوت برای مقایسهی فایلهای متنی ارائه میدهند: diff برای یافتن تفاوتهای خطبهخط و نمایش تغییرات، و comm برای مقایسهی فایلهای مرتبشده و یافتن خطوط مشترک یا منحصربهفرد.
diff (Difference)
دستور diff یکی از پرکاربردترین ابزارهای مقایسهی فایلهاست. این دستور، دو فایل را خطبهخط مقایسه میکند و تفاوتهای آنها را بهصورت مجموعهای از دستورات (برای اعمال تغییرات) نمایش میدهد. diff در نسخههای مختلفی وجود دارد که معروفترین آنها GNU diff است.
ساختار کلی:
diff [option] file1 file2
نحوهی خواندن خروجی diff
خروجی diff بهصورت پیشفرض از دستورات ویرایشی ed (یا patch) استفاده میکند. هر بخش از خروجی با یک خط شروع میشود که محدودهی خطوط و نوع تغییر را نشان میدهد:
| علامت | توضیح |
|---|---|
a | (Add) خطوطی که باید اضافه شوند. |
d | (Delete) خطوطی که باید حذف شوند. |
c | (Change) خطوطی که باید تغییر کنند. |
مثال خروجی:
2c2 < Hello World --- > Hello Universe
-
2c2: خط ۲ فایل اول باید تغییر کند تا با خط ۲ فایل دوم مطابقت داشته باشد. -
< Hello World: خط مربوط به فایل اول. -
---: جداکننده. -
> Hello Universe: خط مربوط به فایل دوم.
گزینههای اصلی diff
| گزینه | توضیح | مثال |
|---|---|---|
-u | خروجی بهصورت Unified Format (خوانا و استاندارد برای patch). | diff -u file1 file2 |
-c | خروجی بهصورت Context Format (با زمینهی بیشتر). | diff -c file1 file2 |
-i | نادیده گرفتن حساسیت به بزرگ/کوچکی. | diff -i file1 file2 |
-w | نادیده گرفتن تفاوتهای فاصلهها و تبها. | diff -w file1 file2 |
-b | نادیده گرفتن تغییرات در تعداد فاصلههای خالی. | diff -b file1 file2 |
-B | نادیده گرفتن خطوط خالی. | diff -B file1 file2 |
-q | فقط نمایش اینکه فایلها متفاوت هستند یا نه (Quiet). | diff -q file1 file2 |
-r | مقایسهی بازگشتی دایرکتوریها. | diff -r dir1 dir2 |
-N | در مقایسهی دایرکتوریها، فایلهای موجود در یک طرف را بهعنوان خالی در نظر بگیر. | diff -rN dir1 dir2 |
-y | نمایش خروجی بهصورت دو ستونی (Side-by-Side). | diff -y file1 file2 |
--color | نمایش خروجی با رنگ. | diff --color file1 file2 |
-s | نمایش زمانی که دو فایل یکسان هستند. | diff -s file1 file2 |
مثالهای پایه
-
مقایسهی دو فایل:
diff file1.txt file2.txt -
مقایسه با خروجی Unified (معمولاً برای patch):
diff -u file1.txt file2.txt
خروجی:
--- file1.txt 2024-01-01 10:00:00 +++ file2.txt 2024-01-01 10:05:00 @@ -1,5 +1,5 @@ Line 1 Line 2 -Hello World +Hello Universe Line 4 Line 5
-
مقایسهی دو دایرکتوری:
diff -r dir1/ dir2/
-
مقایسه و نمایش فقط نام فایلهای متفاوت (با
-q):diff -qr dir1/ dir2/
-
مقایسه با خروجی دو ستونی (با
-y):diff -y file1.txt file2.txt
خروجی:
Line 1 Line 1 Line 2 Line 2 Hello World | Hello Universe Line 4 Line 4 Line 5 Line 5
علامت
|نشاندهندهی تفاوت است. -
نادیده گرفتن تفاوتهای فاصلهها (با
-w):diff -w file1.txt file2.txt
-
نادیده گرفتن تغییرات بزرگ/کوچکی (با
-i):diff -i file1.txt file2.txt
-
مقایسه و نمایش فقط اینکه یکسان هستند یا نه (با
-q):diff -q file1.txt file2.txt
خروجی (اگر متفاوت باشند):
Files file1.txt and file2.txt differ -
مقایسه با رنگ (با
--color):diff --color file1.txt file2.txt
۱. Unified Format (-u)
فرمت Unified (که بهعنوان Unified Diff نیز شناخته میشود) استانداردترین و خواناترین فرمت خروجی diff است که برای ایجاد Patchها و بررسی تغییرات در کد استفاده میشود.
ساختار Unified Diff:
--- file1.txt 2024-01-01 10:00:00 +++ file2.txt 2024-01-01 10:05:00 @@ -1,5 +1,5 @@ Line 1 Line 2 -Hello World +Hello Universe Line 4 Line 5
-
---: فایل اصلی. -
+++: فایل جدید. -
@@ -1,5 +1,5 @@: محدودهی خطوط (از خط ۱ تا ۵ در هر دو فایل). -
خطوط با
-: حذف شدهاند. -
خطوط با
+: اضافه شدهاند. -
خطوط بدون علامت: بدون تغییر باقی ماندهاند (زمینه).
۲. مقایسهی دایرکتوریها با -r و -N
با -r میتوانید دایرکتوریها را بهصورت بازگشتی مقایسه کنید. با -N فایلهایی که فقط در یک دایرکتوری وجود دارند را نیز در خروجی نشان میدهید.
مثال:
diff -rN dir1/ dir2/
خروجی نمونه (زمانی که فایلی فقط در dir1 وجود دارد):
diff -rN dir1/file.txt dir2/file.txt --- dir1/file.txt 2024-01-01 10:00:00 +++ dir2/file.txt 1970-01-01 00:00:00 @@ -1,3 +0,0 @@ -Line 1 -Line 2 -Line 3
۳. خروجی Side-by-Side با -y و کنترل عرض
با استفاده از -y و -W میتوانید عرض خروجی را کنترل کنید:
diff -y -W 80 file1.txt file2.txt
(عرض ۸۰ کاراکتر)
۴. مقایسه با نادیده گرفتن خطوط خالی و فاصلهها
diff -wB file1.txt file2.txt
-
-w: نادیده گرفتن همهی فاصلهها. -
-B: نادیده گرفتن خطوط خالی.
۵. تولید Patch با diff و patch
یکی از کاربردهای اصلی diff تولید فایلهای Patch است که میتوان با دستور patch اعمال کرد.
تولید Patch (با -u):
diff -u file1.txt file2.txt > changes.patch
اعمال Patch:
patch file1.txt < changes.patch
این کار file1.txt را به file2.txt تبدیل میکند.
اعمال Patch بهصورت معکوس (Undo):
patch -R file1.txt < changes.patch
comm (Compare)
دستور comm یک ابزار تخصصی برای مقایسهی دو فایل مرتبشده (Sorted) است. خروجی آن بهصورت سه ستون نمایش داده میشود:
-
ستون اول: خطوطی که فقط در فایل اول وجود دارند.
-
ستون دوم: خطوطی که فقط در فایل دوم وجود دارند.
-
ستون سوم: خطوط مشترک (در هر دو فایل).
ساختار کلی:
comm [option] file1 file2
نکته مهم: هر دو فایل باید مرتبشده باشند (با sort). در غیر این صورت، خروجی comm معتبر نخواهد بود.
گزینههای اصلی comm
| گزینه | توضیح | مثال |
|---|---|---|
-1 | حذف ستون اول (خطوط منحصربهفرد فایل اول). | comm -1 file1 file2 |
-2 | حذف ستون دوم (خطوط منحصربهفرد فایل دوم). | comm -2 file1 file2 |
-3 | حذف ستون سوم (خطوط مشترک). | comm -3 file1 file2 |
-i | نادیده گرفتن حساسیت به بزرگ/کوچکی. | comm -i file1 file2 |
--check-order | بررسی مرتب بودن فایلها. | comm --check-order file1 file2 |
--nocheck-order | عدم بررسی مرتب بودن فایلها. | comm --nocheck-order file1 file2 |
مثالها
فرض کنید دو فایل زیر را داریم:
file1.txt:
apple banana cherry date
file2.txt:
apple cherry grape kiwi
ابتدا آنها را مرتب میکنیم:
sort file1.txt > sorted1.txt sort file2.txt > sorted2.txt
-
مقایسهی دو فایل (خروجی کامل):
comm sorted1.txt sorted2.txtخروجی:
apple banana cherry date grape kiwi-
ستون اول (خالی): خطوط مشترک (
apple،cherry). -
ستون دوم: خطوط فقط در
file1(banana،date). -
ستون سوم: خطوط فقط در
file2(grape،kiwi).
-
-
نمایش فقط خطوط مشترک (با حذف ستونهای ۱ و ۲):
comm -12 sorted1.txt sorted2.txt
خروجی:
apple cherry
-
نمایش خطوط فقط در
file1(با حذف ستونهای ۲ و ۳):comm -23 sorted1.txt sorted2.txt
خروجی:
banana date
-
نمایش خطوط فقط در
file2(با حذف ستونهای ۱ و ۳):comm -13 sorted1.txt sorted2.txt
خروجی:
grape kiwi
-
نادیده گرفتن حساسیت به بزرگ/کوچکی:
comm -i sorted1.txt sorted2.txt
-
بررسی مرتب بودن فایلها (با
--check-order):comm --check-order sorted1.txt sorted2.txtاگر فایلها مرتب نباشند، خطا میدهد.
مقایسهی diff و comm
| ویژگی | diff | comm |
|---|---|---|
| نیاز به مرتبسازی | خیر | بله (هر دو فایل باید مرتب باشند) |
| نوع خروجی | تفاوتهای خطبهخط | خطوط مشترک/منحصربهفرد بر اساس محتوا |
| کاربرد اصلی | یافتن تفاوتها، تولید Patch | یافتن اشتراکها و تفاوتهای مجموعهای |
| مقایسهی دایرکتوری | بله (-r) | خیر |
| خروجی دو ستونی | بله (-y) | خیر (سه ستون) |
| قابلیت تولید Patch | بله | خیر |
| عملکرد بر روی فایلهای بزرگ | مناسب (با گزینههای مختلف) | بسیار سریع (چون خط به خط مقایسه میکند) |
مثالهای ترکیبی و سناریوهای عملی
۱. پیدا کردن خطوط مشترک بین دو لیست
comm -12 <(sort list1.txt) <(sort list2.txt)
استفاده از Process Substitution (<(command)) به شما اجازه میدهد که خروجی یک دستور را بهعنوان فایل به comm بدهید.
۲. پیدا کردن خطوطی که فقط در یک لیست وجود دارند
# خطوط فقط در list1 comm -23 <(sort list1.txt) <(sort list2.txt) # خطوط فقط در list2 comm -13 <(sort list1.txt) <(sort list2.txt)
۳. مقایسهی دو فایل و نمایش تفاوتها بهصورت خلاصه (با diff -q)
diff -q file1.txt file2.txt && echo "Same" || echo "Different"
۴. تولید یک فایل Patch و اعمال آن
diff -u original.txt modified.txt > patch.diff patch original.txt < patch.diff
۵. مقایسهی محتوای دو دایرکتوری و نمایش فایلهای جدید/حذفشده
diff -qr dir1/ dir2/ | grep "Only in"
خطوطی که فقط در یک دایرکتوری وجود دارند را نمایش میدهد.
۶. مقایسهی دو فایل CSV و نمایش تفاوتها بر اساس یک ستون خاص
diff <(cut -d ',' -f 2 file1.csv | sort) <(cut -d ',' -f 2 file2.csv | sort) | grep "^<\|^>"
ستون دوم دو فایل CSV را مقایسه میکند.
۷. یافتن خطوط مشترک بین دو فایل لاگ
comm -12 <(grep "ERROR" log1.log | sort) <(grep "ERROR" log2.log | sort)
خطاهای مشترک بین دو لاگ را پیدا میکند.
۸. استفاده از diff برای پیدا کردن تغییرات در فایلهای پیکربندی
diff -u /etc/ssh/sshd_config.bak /etc/ssh/sshd_config
خلاصه و نکات کلیدی
| ابزار | کاربرد اصلی | گزینههای کلیدی |
|---|---|---|
| diff | مقایسهی خطبهخط فایلها و دایرکتوریها | -u (Unified)، -r (بازگشتی)، -y (دو ستونی)، -q (فقط تفاوت) |
| comm | مقایسهی دو فایل مرتبشده و یافتن خطوط مشترک/منحصربهفرد | -1 (حذف ستون اول)، -2 (حذف ستون دوم)، -3 (حذف ستون سوم) |
نکات کلیدی
-
commنیاز به فایلهای مرتبشده دارد. همیشه قبل از استفاده ازcomm، فایلها را باsortمرتب کنید یا از Process Substitution استفاده کنید. -
diffبرای مقایسهی دقیق و تولید Patch مناسب است، در حالی کهcommبرای مقایسهی مجموعهها (لیستها) و یافتن اشتراکها ایدهآل است. -
فرمت Unified (
-u) درdiffاستانداردترین و خواناترین فرمت برای نمایش تغییرات است و برای تولید Patch بسیار مناسب است. -
مقایسهی دایرکتوریها با
diff -rیکی از روشهای بسیار مفید برای یافتن تفاوتهای بین دو نسخهی یک پروژه است. -
استفاده از Process Substitution (
<(command)) در Bash به شما اجازه میدهد که خروجی دستورات را بهعنوان فایل بهcommوdiffبدهید، بدون نیاز به فایلهای موقت.