Как разнести несколько файлов по каталогам?

19

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

> diff d1/f.cpp d2/f.cpp

или я могу найти различия по каталогам:

> diff d1 d2

но как найти различия только между *.cppфайлами?

> diff d1/*.cpp d2/*.cpp

не похоже на работу (по понятным причинам).

[Вероятно, это легко решить с помощью циклов, но я пытаюсь найти более элегантный способ]

ysap
источник

Ответы:

13

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

for file in d1/*.cpp; do
    diff "$file" "d2/${file##*/}"
done

Или все в одной строке:

for file in d1/*.cpp; do diff "$file" "d2/${file##*/}"; done

${file##*/}Часть представляет собой специальный параметр расширения.

Если переменная file содержит d1/hello.cpp, то "${file##*/}"расширится до hello.cpp(значение файла, но со всем до, включая, последнее / удаленное).

Таким образом "d2/${file##*/}", в результате d2/hello.cppи команда diff, таким образом,diff d1/hello.cpp d2/hello.cpp

Смотрите http://mywiki.wooledge.org/BashFAQ/100 для получения дополнительной информации о манипуляциях со строками в bash.

С другой стороны, система контроля версий (такая как subversion, git, mercurial и т. Д.) Сделает этот тип различий намного проще.

geirha
источник
Я думаю, что из двух отличных ответов этот вопрос более прямолинеен, когда существует несколько типов файлов (хотя я упоминал в вопросе, что ищу решение без циклов), поэтому я принял его. Одно добавленное дополнение находится echo "${file##*/}";перед diffкомандой, поэтому вы знаете, какие файлы на самом деле сравниваются. Кроме того, как упоминалось в ответе @ Rinzwind, этот метод не охватывает случай, когда список файлов не совпадает в обоих каталогах.
ysap
52

diff -qr {DIR1} {DIR2} делает все файлы в обоих каталогах.

  • q показывает только различия
  • rделает рекурсивный Оставьте это, если вам это не нужно

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

-x PAT  --exclude=PAT
    Exclude files that match PAT.

-X FILE    --exclude-from=FILE
   Exclude files that match any pattern in FILE.

исключить файлы. Поэтому, если вам нужен только *.cppсамый простой способ, это создать текстовый файл, в котором перечислены все файлы, которых нет *.cpp. Вы можете сделать это с помощью следующей команды: ls -I "*.cpp" > excluded_filesгде -I "*.cpp"аргумент игнорирует все файлы .cpp. Обратите внимание, что кавычки необходимы.

Rinzwind
источник
Просто и работает без нареканий.
Хосе Гомес
4

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

В частности, он отвечает на мой первоначальный вопрос в том, что он показывает сравнение содержимого каталога в цветовой кодировке и позволяет сравнивать конкретные файлы двойным щелчком по имени файла.

Если нужно более чем трехстороннее сравнение, то gvimdiff(на основе vimредактора) это тоже отличный вариант, который обеспечивает эту функциональность.

ysap
источник
1

Для этого есть легкое решение:

  1. Настройте этот крошечный плагин http://www.vim.org/scripts/script.php?script_id=5309
  2. Сделать diff dir1 dir2 | vim -R -на оболочке

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

Юрий Ершов
источник