Команда Linux diff: сравнение файлов

LinuxBeginner
Практиковаться сейчас

Введение

В ходе этой практической работы мы изучим команду diff — незаменимый инструмент для разработчиков программного обеспечения и системных администраторов, работающих в среде Linux. Команда diff используется для сопоставления содержимого двух файлов и наглядного отображения различий между ними. Этот навык особенно полезен при управлении версиями кода, просмотре изменений в конфигурационных файлах или поиске расхождений в текстовых данных.

Мы смоделируем сценарий разработки программного обеспечения, в котором вы будете использовать команду diff для сравнения различных версий файлов. Это поможет вам понять, как применять данную команду в реальных рабочих ситуациях.

Основы использования diff

Начнем со сравнения двух простых текстовых файлов, чтобы понять базовый формат вывода команды diff.

Для начала перейдите в каталог проекта:

cd /home/labex/project

Теперь воспользуемся командой diff для сравнения двух файлов:

diff file1.txt file2.txt

Вы должны увидеть результат, похожий на этот:

1,2c1,2
< This is version 1 of the file.
< It contains some initial content.
---
> This is version 2 of the file.
> It contains updated content.
4c4
< This is the fourth line.
---
> This is a modified fourth line.

Разберем этот вывод по частям:

  • Числа (например, 1,2c1,2) указывают номера строк в обоих файлах, где обнаружены изменения.
  • Буква c означает "change" (изменение). Другие возможные буквы: a для "add" (добавление) и d для "delete" (удаление).
  • Строки, начинающиеся с символа <, относятся к первому файлу (file1.txt).
  • Строки, начинающиеся с символа >, относятся ко второму файлу (file2.txt).
  • Разделитель --- отделяет содержимое первого файла от содержимого второго.

Этот вывод сообщает нам следующее:

  1. Строки 1 и 2 в обоих файлах различаются.
  2. Строка 4 в обоих файлах различается.
  3. Строка 3 (не показана в выводе) идентична в обоих файлах.

Сравнение скриптов Python

Теперь применим команду diff в более реалистичном сценарии. Представьте, что вы работаете над скриптом Python и хотите сравнить две его версии.

Сначала посмотрим содержимое первой версии скрипта:

cat script_v1.py

Вы увидите:

def greet(name):
    print("Hello, " + name + "!")

def main():
    name = input("Enter your name: ")
    greet(name)

if __name__ == "__main__":
    main()

Теперь взглянем на вторую версию:

cat script_v2.py

Вы увидите:

def greet(name):
    print(f"Hello, {name.capitalize()}!")

def main():
    name = input("Enter your name: ")
    greet(name)
    print("Thank you for using this script!")

if __name__ == "__main__":
    main()

Теперь используем diff для сравнения этих скриптов:

diff script_v1.py script_v2.py

Вывод должен быть примерно таким:

2c2
<     print("Hello, " + name + "!")
---
>     print(f"Hello, {name.capitalize()}!")
6a7
>     print("Thank you for using this script!")

Этот результат говорит нам о следующем:

  1. Строка 2 была изменена. Теперь приветствие использует f-строку и выводит имя с заглавной буквы.
  2. Была добавлена новая строка (строка 7 в новой версии) с благодарственным сообщением.

Использование унифицированного формата

Унифицированный формат (опция -u) обеспечивает более читаемый вывод, что особенно полезно для больших файлов или когда важен контекст изменений.

Сравните Python-скрипты, используя унифицированный формат:

diff -u script_v1.py script_v2.py

Вы должны увидеть результат, похожий на этот:

--- script_v1.py 2023-12-28 10:00:00.000000000 +0000
+++ script_v2.py 2023-12-28 10:05:00.000000000 +0000
@@ -1,8 +1,9 @@
 def greet(name):
-    print("Hello, " + name + "!")
+    print(f"Hello, {name.capitalize()}!")

 def main():
     name = input("Enter your name: ")
     greet(name)
+    print("Thank you for using this script!")

 if __name__ == "__main__":

Разберем этот формат:

  • Первые две строки показывают сравниваемые файлы и временные метки их изменения.
  • Строки, начинающиеся с -, присутствуют в первом файле (script_v1.py), но отсутствуют или изменены во втором.
  • Строки, начинающиеся с +, добавлены во второй файл (script_v2.py).
  • Строки без знаков - или + служат для контекста и остались неизменными в обоих файлах.
  • Строка @@ -1,8 +1,9 @@ указывает, что мы видим фрагмент с 1 по 8 строку первого файла и с 1 по 9 строку второго.

Этот формат часто является предпочтительным, так как он наглядно показывает окружение, в котором произошли изменения.

Игнорирование изменений в пробелах

Иногда различия в пробелах или табуляции не имеют значения для логики работы. Опция -w заставляет diff игнорировать такие изменения.

Создадим новую версию нашего скрипта с добавлением лишних пробелов:

Примечание: Вам нужно добавить пробелы в скрипт вручную, так как простое копирование и вставка кода может не сохранить специфическое форматирование пробелов.

cat > script_v3.py << EOF
def greet(name):
    print(f"Hello, {name.capitalize()}!")

def main():
    name = input("Enter your name: ")
    greet(name)
    print("Thank you for using this script!")

if __name__ == "__main__":
    main()
EOF

Теперь сравним script_v2.py и script_v3.py сначала без опции, а затем с опцией -w:

diff script_v2.py script_v3.py

Вы можете увидеть различия, вызванные пробелами. Теперь попробуйте:

diff -w script_v2.py script_v3.py

Вывод должен быть пустым, что означает отсутствие значимых различий при игнорировании пробелов.

Это очень полезно, когда вы хотите сосредоточиться на изменениях в логике кода, а не на правках форматирования.

Сравнение каталогов

Команда diff также умеет сравнивать целые директории. Давайте создадим две папки с файлами и сопоставим их.

Создайте директории и файлы:

echo "This is a file in dir1" > dir1/file.txt
echo "This is a file in dir2" > dir2/file.txt
echo "This file is unique to dir1" > dir1/unique1.txt
echo "This file is unique to dir2" > dir2/unique2.txt

Теперь сравните каталоги:

diff -r dir1 dir2

Вы должны увидеть результат, похожий на этот:

Only in dir1: unique1.txt
Only in dir2: unique2.txt
diff -r dir1/file.txt dir2/file.txt
1c1
< This is a file in dir1
---
> This is a file in dir2

Этот вывод сообщает нам:

  1. В dir1 есть файл unique1.txt, которого нет в dir2.
  2. В dir2 есть файл unique2.txt, которого нет в dir1.
  3. Файл file.txt присутствует в обоих каталогах, но его содержимое различается.

Опция -r заставляет diff выполнять рекурсивное сравнение, включая все подкаталоги, что незаменимо при анализе сложных структур проектов.

Резюме

В ходе этой лабораторной работы мы изучили команду Linux diff в контексте разработки программного обеспечения. Мы научились:

  1. Сравнивать два текстовых файла и интерпретировать базовый вывод diff.
  2. Сравнивать различные версии скриптов Python.
  3. Использовать унифицированный формат для получения более наглядных результатов.
  4. Игнорировать изменения в пробелах при сравнении.
  5. Выполнять рекурсивное сравнение целых директорий.

Дополнительные полезные опции diff, не затронутые в этой работе:

  • -y: Сравнение в две колонки (side-by-side).
  • -i: Игнорирование регистра символов.
  • -b: Игнорирование изменений в количестве пробелов.
  • -B: Игнорирование изменений в пустых строках.
  • -q: Вывод только факта наличия различий без показа самих изменений.

Эти параметры можно комбинировать для решения специфических задач по анализу файлов.