Bash сравнить имена файлов

Обновлено: 07.07.2024

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

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

Сравнение файлов diff

Утилита diff linux - это программа, которая работает в консольном режиме. Ее синтаксис очень прост. Вызовите утилиту, передайте нужные файлы, а также задайте опции, если это необходимо:

$ diff опции файл1 файл2

Можно передать больше двух файлов, если это нужно. Перед тем как перейти к примерам, давайте рассмотрим опции утилиты:

  • -q - выводить только отличия файлов;
  • -s - выводить только совпадающие части;
  • -с - выводить нужное количество строк после совпадений;
  • -u - выводить только нужное количество строк после отличий;
  • -y - выводить в две колонки;
  • -e - вывод в формате ed скрипта;
  • -n - вывод в формате RCS;
  • -a - сравнивать файлы как текстовые, даже если они не текстовые;
  • -t - заменить табуляции на пробелы в выводе;
  • -l - разделить на страницы и добавить поддержку листания;
  • -r - рекурсивное сравнение папок;
  • -i - игнорировать регистр;
  • -E - игнорировать изменения в табуляциях;
  • -Z - не учитывать пробелы в конце строки;
  • -b - не учитывать пробелы;
  • -B - не учитывать пустые строки.

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

К тому же, линии, которые отличаются, будут обозначаться символом <, а те, которые совпадают - символом >.

Вот содержимое наших тестовых файлов:


Теперь давайте выполним сравнение файлов diff:

diff file1 file2


В результате мы получим строчку: 2,3c2,4. Она означает, что строки 2 и 3 были изменены. Вы можете использовать опции для игнорирования регистра:

diff -i file1 file2

Можно сделать вывод в две колонки:

diff -y file1 file2


А с помощью опции -u вы можете создать патч, который потом может быть наложен на такой же файл другим пользователем:

diff -u file1 file2


Чтобы обработать несколько файлов в папке удобно использовать опцию -r:


diff -u file1 file2 > file.patch


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

Сравнение файлов Linux с помощью GUI

Существует несколько отличных инструментов для сравнения файлов в linux в графическом интерфейсе. Вы без труда разберетесь как их использовать. Давайте рассмотрим несколько из них:

1. Kompare


Kompare - это графическая утилита для работы с diff, которая позволяет находить отличия в файлах, а также объединять их. Написана на Qt и рассчитана в первую очередь на KDE. Кроме сравнения файлов утилита поддерживает сравнение каталогов и позволяет создавать и применять патчи к файлам.

2. Meld


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

3. Diffuse


Diffuse - еще один популярный и достаточно простой инструмент для сравнения и слияния файлов. Он написан на Python 2. Поэтому в современных версиях Ubuntu программу будет сложно установить. Поддерживается две основные возможности - сравнение файлов и управление версиями. Вы можете редактировать файлы прямо во время просмотра.

4. KDiff3


KDiff3 - еще один отличный, свободный инструмент для сравнения файлов в окружении рабочего стола KDE. Он входит в набор программ KDevelop и работает на всех платформах, включая Windows и MacOS. Можно выполнить сравнение до трех файлов Linux или даже сравнить каталоги. Кроме того, есть поддержка слияния и ручного выравнивания.

5. TkDiff


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

Выводы

В этой статье мы рассмотрели как выполняется сравнение файлов linux с помощью терминала, как создавать патчи, а также сделали небольшой обзор лучших графических утилит для сравнения файлов. А какие инструменты для сравнения используете вы? Напишите в комментариях!

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

MyFile123432 20150510230000.xlsx

MyFile999996 20150510230000.xlsx

Это уникальная проблема, и я не знаю, с чего начать. Пожалуйста, помогите.

4 ответа

Решение на основе awk:

Или вы можете использовать свои стандартные инструменты coreutil :

Он определит, какие необычные записи отсутствуют в каком файле. Вы также можете манипулировать необычными именами файлов как угодно, например расширение параметра / извлечение подстроки, удаление подстроки или индексы символов.

Итак, если первый файл - это FILE1 , а второй файл - FILE2 , то если цель состоит только в том, чтобы идентифицировать файлы в FILE2 , которых нет в FILE1 , следующее должно сделать:

Вкратце, это меняет местами символы в каждой строке и извлекает интересующую вас часть, сохраняя во временный файл для каждого списка файлов. Переворачивание символов выполняется, поскольку вы не сказали, гарантированно ли длина имен файлов будет постоянной - единственное, на что мы можем здесь положиться, это то, что последние 19 символов имеют фиксированный формат (в данном случае (хотя формат легко определить, на самом деле он не имеет значения). Сортировка важна для того, чтобы diff показал вам, чего нет во втором файле, чем в первом.

Если вы уверены, что когда-либо будут отсутствовать файлы только в FILE2 , а не наоборот (то есть файлы в FILE2 , которых нет в FILE1 ), тогда вы можете очистить вещи, удалив беспорядок, введенный diff , поэтому последняя строка станет:

grep ограничивает вывод теми строками с именами файлов xlsx , а sed удаляет все в строке, начиная с первого встретившегося пробела.

Конечно, технически это только говорит вам, какие сгруппированные по времени группы файлов существуют в FILE1 , но не FILE2 - насколько я понимаю, это то, что вы вы ищете (насколько я понимаю из описания вашей проблемы, MyFile12343220150510230000.xlsx и MyFile99999620150510230000.xlsx будут иметь идентичное содержание). Если имена файлов всегда имеют одинаковую длину (как вы впоследствии подтвердили), тогда нет необходимости в rev , и команды вырезания можно просто изменить, чтобы они ссылались на фиксированные позиции символов.

В любом случае, чтобы получить окончательный список файлов, вам нужно будет использовать «очищенный» вывод для фильтрации содержимого FILE1 ; Итак, изменив приведенный выше сценарий так, чтобы он включал команду "очистки", мы можем отфильтровать нужные файлы с помощью grep - тогда весь сценарий будет выглядеть так:

Расширенная команда grep ( -E ) просто создает регулярное выражение "или" для каждого расширения "отметка времени" и применяет его к первому файлу. Конечно, все это предполагает, что никогда не будет групп временных меток, которые существуют в FILE2 , а не в FILE1 - если это так , то "diff «обработка вывода» должна быть немного умнее.

Сначала вы можете использовать comm , чтобы сопоставить точные имена файлов и получить список файлов, которые не совпадают. Затем вы можете воспользоваться соглашением. Я никогда им не пользовался, но может оказаться полезным.

Или, как последний вариант, вы можете выполнить перебор и для каждой строки в первом файле искать во втором:

Здесь я предположил, что имена файлов заканчиваются 14 цифрами, которые должны совпадать в другом файле, и расширением файла, которое может отличаться от файла к файлу, но оно тоже должно совпадать:


Как найти два файла с совпадающими данными в сценарии оболочки и дубликат хранилища данных в другом файле оболочки?

Я написал код, но он не работал. Как это написать?

Чтобы просто проверить, совпадают ли два файла, используйте cmp -s :

Если ваши два входных файла содержит список путей файлов, которые вы хотите сравнить, используйте двойной цикл, например:

Здесь результат создается как на терминале, так и в файле file-comparison.out .

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

Код сначала считывает все пути из одного из файлов в массив, files1 , с помощью mapfile . Я делаю это, чтобы не читать этот файл более одного раза, так как нам придется просматривать все эти пути для каждого пути в другом файле. Вы заметите, что вместо чтения из $filelist1 во внутреннем цикле я просто перебираю имена в files1 массив.

  • мне нужна полная программа в оболочке bash
  • @santhoshreddy См. обновленный ответ.

Самый простой способ - использовать команду diff .

пример:

предположим, что первый файл file1.txt и он содержит:

и второй файл file2.txt

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

diff file1.txt file2.txt

Давайте посмотрим, что означает этот вывод. Важно помнить, что когда diff описывает вам эти различия, он делает это в предписывающем контексте: он сообщает вам, как изменить первый файл, чтобы он соответствовал второму файлу. Первая строка вывода diff будет содержать:

  • номера строк, соответствующие первому файлу,
  • буква (a для добавления, c для изменения или d для удаления)
  • номера строк, соответствующие второму файлу.

Вот чистый сценарий оболочки bash для сравнения файлов:

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

Доброго дня господа.
Есть вопрос на весьма тривиальную задачку.
Есть 2 списка ссылок на файлы. Для примера:

Я хочу сравнить эти два списка, а точнее проверить наличие всех файлов с списка 1 в списке 2, и получить 2 ссылки на 2 файла c 100% идентичными именами (ака /home/user/.test -> /home/user/dir/.test).
Я пошел стандартным путём.
Для каждой строки из списка 1 - искал совпадения в списке 2.
На практике: И столкнулся с тем, что греп даёт мне первой строкой не идеальное совпадение, а что-то другое (не всегда, но тут так).
Если творить через точный шаблон (grep -x) - нужно городить еще один for в for'e, как я это вижу (через awk, к примеру).
Но это какой-то подводный костыль с диким оверхэдом.
Как это было бы разумней сделать по-красоте?
Спасибо адекватно ответившим.




И как мне это конкретно в этой ситуации использовать? Не совсем понял.


Например, sed'ом вырезаешь корневые пути у списков и grep -f list1 list2



Вот только точку в имени файла оно воспринимает как часть регекспа. Косяк.


Вот так работает, но костыль, конечно.



Блин, для таких вещей Ruby есть. Не сложнее школьного бейсика.


Сначала отрезать общий префикс. Каждому списку сделать sort и uniq. Списки слить (sort -m). Сделать uniq -c. awk-ом выбрать все строки, у которых в первом столбце двойка — они присутствуют в обоих списках.


Это не одноразовая задача, и обязательное условие - баш.
ЗЫ: и да, творение гения Мацумото - тут было бы очень кстати, но не всё в жизни так просто :D



Это grep в данном случае — танцы. А у меня — простое и элегантное (и быстрое!) решение. Ты б еще на каждую букву по отдельному процессу рожал.

geekless ★★ ( 26.10.12 22:42:01 )
Последнее исправление: geekless 26.10.12 22:42:26 (всего исправлений: 1)


Окей, пойдём по пунктам:

Будь добр, укажи где было сказано что они имеют общий префикс?
Без тянучки - нет, общего префикса нету, сравниваю только файлы, о чём и написал

у которых в первом столбце двойка — они присутствуют в обоих списках

Опустим сказанное выше, сделаем вид что еще актуально:
А задачу ты так и не сумел прочесть? Мне нужно получить пару из ссылок.
Как её получить в итогах? Таки отгрепать? ;)
Ну или еще пару действий, простых инструментов не пользуем, ни в коем.


Будь добр, укажи где было сказано что они имеют общий префикс?

Шо я такое вижу?


И? Ты видишь не существующие файлы, для примера, если верить тому, что я написал :)
Никаких указаний что это паттерны нет.

Читайте также: