Lệnh diff trong Linux — So sánh nội dung hai tệp tin

Bạn đã bao giờ rơi vào tình huống phải đối soát hàng nghìn dòng cấu hình trên VPS và cảm thấy chóng mặt vì không biết sự khác biệt nằm ở đâu chưa nhỉ? Với tư cách là một Senior System Admin, tôi đã từng phải xử lý những sự cố cực kỳ căng thẳng khi so sánh sự sai lệch giữa các file log quan trọng để tìm ra nguyên nhân lỗi hệ thống. Đó là lúc tôi nhận ra rằng, nếu không nắm vững cách dùng diff, công việc quản trị sẽ trở nên vô cùng khó khăn. Vậy thực chất diff là gì và tại sao nó lại là "vũ khí" không thể thiếu của mọi kỹ sư? Trong bài viết này, chúng ta sẽ cùng khám phá chi tiết về diff Linux, giúp bạn nắm bắt cách so sánh nội dung giữa hai tệp tin một cách nhanh chóng và chính xác nhất. Tất nhiên, việc hiểu rõ diff là gì sẽ giúp bạn làm chủ hoàn toàn cách so sánh tệp tin một cách chuyên nghiệp, đúng không nào?

Cần chuẩn bị gì trước khi dùng lệnh diff?

  • Quyền user: Người dùng có quyền truy cập thông thường để đọc các tệp tin cần so sánh.
  • Distro/OS hỗ trợ: Hỗ trợ hầu hết các hệ điều hành dựa trên Unix/Linux như Ubuntu, Debian, CentOS, Fedora, RHEL và macOS.
  • Package dependencies: Lệnh diff thường được cài đặt sẵn trong gói coreutils. Nếu hệ thống chưa có, có thể cài đặt bằng lệnh:
    • Ubuntu/Debian: sudo apt-get install diffutils
    • CentOS/RHEL: sudo yum install diffutils

Cú pháp lệnh diff là gì?

Lệnh diff hỗ trợ nhiều dạng cú pháp khác nhau trên hệ điều hành Linux để so sánh các tệp tin hoặc thư mục.

diff [OPTION]... FILE [FILE]...
diff [OPTION]... DIRECTORY [DIRECTORY]...

Các tùy chọn của lệnh diff là gì?

Lệnh diff cung cấp nhiều tùy chọn được phân theo các nhóm chức năng: kiểm soát định dạng đầu ra, so sánh nội dung, xử lý thư mục và tùy chỉnh cách đọc dữ liệu.

Tùy chọn ngắn Tùy chọn dài Mô tả
-u --unified diff -u hiển thị đầu ra theo định dạng unified, bao gồm các dòng ngữ cảnh xung quanh phần thay đổi.
-c --context diff -c hiển thị đầu ra theo định dạng context, liệt kê các dòng thay đổi kèm ngữ cảnh trước và sau.
-e --ed diff -e xuất đầu ra theo định dạng ed script, cho phép áp dụng trực tiếp bằng trình soạn thảo ed.
-n --rcs diff -n xuất đầu ra theo định dạng RCS diff, thường dùng trong hệ thống quản lý phiên bản RCS.
-y --side-by-side diff -y hiển thị hai tập tin song song theo từng cột, giúp so sánh trực quan hơn.
-W --width diff -W đặt độ rộng tối đa của đầu ra khi dùng chế độ side-by-side. Mặc định là 130 ký tự.
-r --recursive diff -r so sánh đệ quy toàn bộ các tập tin bên trong hai thư mục.
-q --brief diff -q chỉ báo cáo khi hai tập tin khác nhau, không hiển thị chi tiết nội dung thay đổi.
-s --report-identical-files diff -s thông báo khi hai tập tin hoàn toàn giống nhau.
-i --ignore-case diff -i bỏ qua sự khác biệt về chữ hoa và chữ thường khi so sánh.
-w --ignore-all-space diff -w bỏ qua toàn bộ khoảng trắng khi so sánh nội dung các dòng.
-b --ignore-space-change diff -b bỏ qua sự thay đổi về số lượng khoảng trắng giữa các từ.
-B --ignore-blank-lines diff -B bỏ qua các thay đổi chỉ liên quan đến dòng trống.
-E --ignore-tab-expansion diff -E bỏ qua sự khác biệt do ký tự tab và khoảng trắng tương đương gây ra.
-Z --ignore-trailing-space diff -Z bỏ qua khoảng trắng ở cuối mỗi dòng khi so sánh.
-I --ignore-matching-lines diff -I bỏ qua các dòng khớp với biểu thức chính quy được chỉ định.
-a --text diff -a xử lý tất cả các tập tin như tập tin văn bản, kể cả tập tin nhị phân.
--strip-trailing-cr --strip-trailing-cr diff --strip-trailing-cr loại bỏ ký tự carriage return ở cuối dòng trước khi so sánh, hữu ích khi so sánh tập tin giữa Windows và Linux.
-D --ifdef diff -D hợp nhất hai tập tin thành một đầu ra duy nhất dùng cú pháp #ifdef của C preprocessor.
-l --paginate diff -l phân trang đầu ra thông qua lệnh pr trước khi in.
-t --expand-tabs diff -t chuyển đổi ký tự tab thành khoảng trắng trong đầu ra để căn chỉnh đúng cột.
-T --initial-tab diff -T thêm một ký tự tab ở đầu mỗi dòng đầu ra để căn lề thống nhất.
--tabsize --tabsize diff --tabsize đặt số lượng khoảng trắng tương đương với một ký tự tab. Mặc định là 8.
-p --show-c-function diff -p hiển thị tên hàm C gần nhất trong phần tiêu đề của mỗi khối thay đổi.
-F --show-function-line diff -F hiển thị dòng gần nhất khớp với biểu thức chính quy được chỉ định trong phần tiêu đề của mỗi khối thay đổi.
-U --unified=NUM diff -U hiển thị NUM dòng ngữ cảnh trong định dạng unified. Mặc định là 3 dòng.
-C --context=NUM diff -C hiển thị NUM dòng ngữ cảnh trong định dạng context. Mặc định là 3 dòng.
-x --exclude diff -x loại trừ các tập tin khớp với mẫu tên được chỉ định khi so sánh thư mục.
-X --exclude-from diff -X đọc danh sách các mẫu loại trừ từ một tập tin được chỉ định.
-N --new-file diff -N coi tập tin vắng mặt trong một thư mục như một tập tin rỗng khi so sánh thư mục.
--unidirectional-new-file --unidirectional-new-file diff --unidirectional-new-file coi tập tin vắng mặt trong thư mục thứ nhất như tập tin rỗng, chỉ theo một chiều.
-S --starting-file diff -S bắt đầu so sánh thư mục từ tập tin được chỉ định thay vì từ đầu danh sách.
--from-file --from-file diff --from-file so sánh tập tin hoặc thư mục được chỉ định với tất cả các đối số còn lại.
--to-file --to-file diff --to-file so sánh tất cả các đối số với tập tin hoặc thư mục được chỉ định.
--horizon-lines --horizon-lines diff --horizon-lines giữ lại số dòng tiền tố và hậu tố chỉ định để cải thiện chất lượng so sánh.
-d --minimal diff -d cố gắng tìm ra tập hợp thay đổi nhỏ nhất có thể, cho ra đầu ra chính xác hơn nhưng tốn nhiều tài nguyên hơn.
--speed-large-files --speed-large-files diff --speed-large-files tối ưu tốc độ xử lý cho các tập tin lớn có nhiều thay đổi nhỏ rải rác.
--color --color diff --color tô màu đầu ra để phân biệt trực quan giữa các dòng thêm, xóa và ngữ cảnh.
--palette --palette diff --palette tùy chỉnh bảng màu được dùng khi hiển thị đầu ra có màu.
-v --version diff -v hiển thị thông tin phiên bản của lệnh diff.
--help diff --help hiển thị hướng dẫn sử dụng và danh sách tùy chọn của lệnh diff.

xem thêm: Text Processing and Editing

Cách sử dụng lệnh diff để so sánh dữ liệu thực tế?

Dưới đây là các tình huống sử dụng lệnh diff phổ biến trong quản trị hệ thống và quản lý mã nguồn.

diff là gì? [So sánh hai tệp tin cơ bản]

$ diff file1.txt file2.txt
2c2
< original_line
---
> updated_line

Lệnh hiển thị sự khác biệt giữa hai tệp tin tại dòng số 2. Trong thực tế, đây là cách nhanh nhất để kiểm tra các thay đổi nhỏ trong các tệp cấu hình đơn giản.

diff -u là gì? [Xem thay đổi dạng Unified format]

$ diff -u file1.txt file2.txt
--- file1.txt
+++ file2.txt
@@ -1,3 +1,3 @@
 line1
-original_line
+updated_line
 line3

Lệnh hiển thị sự khác biệt dưới định dạng Unified, sử dụng dấu "+" và "-" để biểu thị nội dung mới và cũ. Trên môi trường production, định dạng này được ưu tiên vì dễ đọc và là tiêu chuẩn để tạo các tệp patch.

diff -r là gì? [So sánh toàn bộ thư mục]

$ diff -r config_old/ config_new/
Files config_old/nginx.conf and config_new/nginx.conf differ
Only in config_new/: settings.json

Lệnh thực hiện so sánh đệ quy tất cả các tệp nằm trong hai thư mục. Đây là tình huống sysadmin thường gặp khi cần kiểm tra sự khác biệt giữa các phiên bản cấu hình hệ thống hoặc kiểm tra tính toàn vẹn của mã nguồn sau khi deploy.

diff -rq là gì? [Chỉ liệt kê danh sách tệp khác biệt]

$ diff -rq dir1/ dir2/
Files dir1/app.log and dir2/app.log differ
Only in dir2/: backup.sql

Lệnh kết hợp tham số -r (đệ quy) và -q (tóm tắt) để chỉ thông báo danh sách các tệp có sự khác biệt mà không hiển thị nội dung chi tiết. Trong các kịch bản automation hoặc script kiểm tra hệ thống, cách tiếp cận này giúp tối ưu hóa tốc độ xử lý và dễ dàng lọc kết quả.

Sử dụng lệnh diff gặp lỗi thường gặp là gì?

Trong quá trình so sánh các tệp tin hoặc thư mục, người dùng thường gặp phải các vấn đề liên quan đến quyền truy cập, đường dẫn không tồn tại hoặc sự khác biệt về định dạng tệp.

Lỗi không tìm thấy tệp tin (No such file or directory)

diff file_a.txt file_b.txt
diff: cannot open file_a.txt: No such file or directory
Try 'cd' to see if file_a.txt exists.

Lỗi xảy ra khi đường dẫn tệp tin cung cấp không chính xác hoặc tệp tin không tồn tại trong thư mục hiện hành.

Lỗi không có quyền truy cập (Permission denied)

diff /etc/shadow /etc/passwd
diff: cannot open /etc/shadow for reading: Permission denied

Lỗi xuất hiện khi người dùng thực hiện lệnh so sánh các tệp tin hệ thống yêu cầu quyền quản trị (root) để đọc.

Lỗi so sánh hai thư mục không đồng nhất

diff dir_a dir_b
diff: directory dir_b does not exist

Lỗi xảy ra khi một trong hai tham số truyền vào là tên thư mục nhưng thư mục đó không tồn tại trên hệ thống.

Lỗi so sánh tệp tin nhị phân (Binary files differ)

diff image1.png image2.png
Binary files image1.png and image2.png differ

Khi so sánh các tệp không phải định dạng văn bản, diff không thể hiển thị các dòng khác biệt mà chỉ thông báo sự khác nhau giữa các tệp nhị phân.

Quy trình thực tế dùng diff để kiểm soát thay đổi mã nguồn trong dự án Linux?

Trong quá trình phát triển phần mềm, lệnh diff đóng vai trò quan trọng khi so sánh các phiên bản mã nguồn để phát hiện sai lệch trước khi thực hiện merge hoặc triển khai lên server.

Bước 1: Kiểm tra sự khác biệt giữa hai tệp tin cấu hình

diff config_v1.conf config_v2.conf
0c1
< line_limit=100
---
> line_limit=200

Lệnh cho phép bạn xác định các dòng nội dung bị thay đổi, thêm mới hoặc xóa bỏ giữa hai phiên bản cấu hình.

Bước 2: Xuất các thay đổi ra tệp tin định dạng patch

diff -u original.py updated.py > changes.patch

Sử dụng tham số -u để tạo ra tệp patch dưới định dạng Unified Format, giúp việc lưu trữ và chia sẻ các thay đổi trở nên chuyên nghiệp hơn.

Bước 3: Áp dụng các thay đổi từ tệp patch vào mã nguồn gốc

patch original.py < changes.patch
patching file original.py

Sau khi kiểm tra nội dung tệp patch, bạn có thể dùng lệnh patch để cập nhật trực tiếp các thay đổi vào tệp tin gốc một cách tự động.

Trong thực tế quản trị VPS, việc sử dụng lệnh diff đòi hỏi sự chính xác về đường dẫn tệp để tránh so sánh nhầm dữ liệu. Khi thực hiện so sánh các tệp cấu hình hệ thống trên VPS, sự khác biệt về ký tự xuống dòng (line endings) giữa định dạng Windows (CRLF) và Linux (LF) dẫn đến kết quả diff không chính xác. Người dùng cần sử dụng thêm tham số --strip-trailing-whitespace để loại bỏ các khoảng trắng dư thừa trong quá trình so sánh. Đối với các tệp tin lớn, việc chạy lệnh diff trực tiếp có thể gây tiêu tốn tài nguyên hệ thống. Trong các kịch bản tự động hóa trên VPS, việc điều hướng kết quả đầu ra thông qua toán tử redirection giúp lưu trữ sự khác biệt vào một tệp nhật ký cụ thể. Ví dụ: diff file1.txt file2.txt > result.patch. Việc kiểm soát định dạng encoding là yếu tố then chốt để lệnh diff trả về kết quả thực tế thay vì các ký tự lạ.

Những câu hỏi thường gặp về lệnh diff?

Dưới đây là tổng hợp các tình huống phổ biến mà người dùng thường gặp khi sử dụng lệnh diff để so sánh dữ liệu.

Làm thế nào để xem sự khác biệt giữa hai tệp một cách dễ đọc nhất?

Sử dụng tham số -u để hiển thị nội dung dưới định dạng unified diff, giúp dễ dàng theo dõi các dòng được thêm vào hoặc xóa đi.

diff -u file1.txt file2.txt
--- file1.txt
+++ file2.txt
@@ -1,3 +1,3 @@
 Hello
-World
+Linux
 Goodbye

Làm sao để bỏ qua sự khác biệt về khoảng trắng khi so sánh?

Tham số -w cho phép lệnh diff bỏ qua tất cả các khoảng trắng để tập trung vào sự thay đổi của nội dung văn bản.

diff -w file1.txt file2.txt

Làm thế nào để so sánh hai thư mục thay vì hai tệp đơn lẻ?

Sử dụng tham số -r để thực hiện so sánh đệ quy, cho phép kiểm tra sự khác biệt giữa các tệp trong cùng cấu trúc thư mục.

diff -r dir1/ dir2/
Only in dir1/: config.cfg
Only in dir2/: script.sh
```

Làm cách nào để tìm các dòng giống nhau giữa hai tệp?

Sử dụng tham số -s để yêu cầu lệnh diff thông báo nếu hai tệp hoàn toàn giống nhau.

diff -s file1.txt file2.txt
Files file1.txt and file2.txt are identical

Làm thế nào để chỉ hiển thị những dòng có sự khác biệt?

Sử dụng tham số -y để hiển thị kết quả theo dạng hai cột song song, giúp người dùng dễ dàng đối chiếu trực quan.

diff -y file1.txt file2.txt
Hello          Hello
World         | Linux
Goodbye        Goodbye

Làm sao để bỏ qua sự khác biệt về chữ hoa và chữ thường?

Sử dụng tham số -i để lệnh diff coi các ký tự viết hoa và viết thường là tương đương nhau.

diff -i file1.txt file2.txt

Lệnh diff là một công cụ vô cùng mạnh mẽ giúp bạn so sánh sự khác biệt giữa các tệp tin hoặc thư mục một cách chính xác. Việc sử dụng các tham số như -u để tạo định dạng unified hay -r để so sánh các thư mục có thể giúp bạn nhanh chóng kiểm soát các thay đổi trong mã nguồn, đúng không nhỉ? Bạn hoàn toàn có thể làm chủ quy trình rà soát dữ liệu và quản lý phiên bản hiệu quả hơn nhờ sức mạnh của nó. Hy vọng những kiến thức này sẽ hỗ trợ bạn thật tốt trong quá trình làm việc với Linux. Chúc bạn thành công!