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


19

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

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

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

> diff d1 d2

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

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

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

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

Ответы:


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 и т. Д.) Сделает этот тип различий намного проще.


Я думаю, что из двух отличных ответов этот вопрос более прямолинеен, когда существует несколько типов файлов (хотя я упоминал в вопросе, что ищу решение без циклов), поэтому я принял его. Одно добавленное дополнение находится 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. Обратите внимание, что кавычки необходимы.


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

4

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

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

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


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.