Подтвердить что ты не робот

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

Прежде чем перейти к использованию SVN, я использовал для управления моим проектом, просто сохраняя каталог /develop/ и редактируя и тестируя файлы там, а затем перемещая их в каталог /main/. Когда я решил перейти на SVN, мне нужно было убедиться, что каталоги действительно синхронизированы.

Итак, что такое хороший способ написать оболочку script [bash] для рекурсивного сравнения файлов с тем же именем в двух разных каталогах?

Примечание. Названия каталогов, используемые выше, относятся только к образцу. Я не рекомендую хранить ваш код на верхнем уровне:).

4b9b3361

Ответ 1

Команда diff имеет параметр -r для рекурсивного сравнения каталогов:

diff -r /develop /main

Ответ 2

diff -rqu /develop /main

Это даст вам только краткое изложение изменений:)

Если вы хотите видеть только новые/отсутствующие файлы

diff -rqu /develop /main | grep "^Only

Если вы хотите их обнажить:

diff -rqu /develop /main | sed -rn "/^Only/s/^Only in (.+?): /\1/p"

Ответ 3

У меня есть доступная возможность рекурсивных различий:

diff -r main develop

Но с оболочкой script:

( cd main ; find . -type f -exec diff {} ../develop/{} ';' )

Ответ 4

[Я где-то читал, что ответы на ваши собственные вопросы в порядке, так вот идет:)]

Я пробовал это, и он работал довольно хорошо

[/]$ cd /develop/
[/develop/]$ find | while read line; do diff -ruN "/main/$line" $line; done |less

Вы можете сравнить только определенные файлы (например, только .php), отредактировав приведенную выше строку как

[/]$ cd /develop/
[/develop/]$ find -name "*.php" | while read line; do diff -ruN "/main/$line" $line; done |less

Любые другие идеи?

Ответ 5

вот пример (несколько грязный) script, dircompare.sh, который будет:

  • сортировать файлы и каталоги в массивах в зависимости от того, в какой директории они происходят (или и то и другое), в двух рекурсивных проходах
  • Файлы, которые встречаются в обоих каталогах, сортируются снова в двух массивах, в зависимости от того, если diff -q определяет, отличаются ли они или нет
  • для тех файлов, которые соответствуют утверждениям diff, показывают и сопоставляют временные метки

Надеюсь, что это окажется полезным - Приветствия!

EDIT2: (На самом деле, он отлично работает с удаленными файлами - проблема была необработанным сигналом Ctrl-C во время операции diff между локальным и удаленным файлами, что может занять некоторое время; script теперь обновляется с помощью ловушки для обработки этого - однако, оставив предыдущее правление ниже для справки):

EDIT:... за исключением того, что он, похоже, разбивает мой сервер на удаленный каталог ssh (который я пытался использовать поверх ~/.gvfs)... Значит, это не bash, но альтернатива, я думаю, заключается в использовании rsync, вот пример:

$ # get example revision 4527 as testdir1
$ svn co https://openbabel.svn.sf.net/svnroot/openbabel/openbabel/trunk/[email protected] testdir1

$ # get earlier example revision 2729 as testdir2
$ svn co https://openbabel.svn.sf.net/svnroot/openbabel/openbabel/trunk/[email protected] testdir2

$ # use rsync to generate a list 
$ rsync -ivr --times --cvs-exclude --dry-run testdir1/ testdir2/
sending incremental file list
.d..t...... ./
>f.st...... CMakeLists.txt
>f.st...... MACCS.txt
>f..t...... SMARTS_InteLigand.txt
...
>f.st...... atomtyp.txt
>f+++++++++ babel_povray3.inc
>f.st...... bin2hex.pl
>f.st...... bondtyp.h
>f..t...... bondtyp.txt
...

Обратите внимание, что:

  • Чтобы получить вышеизложенное, вы не должны забывать конечные косые черты / в конце имен каталогов в rsync
  • --dry-run - имитировать только, не обновлять/передавать файлы
  • -r - рекурсия в директории
  • -v - подробный (но не, связанный с информацией об изменениях файла)
  • --cvs-exclude - игнорировать .svn файлы
  • -i - "--itemize-changes: выводить сводку изменений для всех обновлений"

Вот краткий отрывок man rsync, который объясняет информацию, показанную -i (например, строки >f.st...... выше):

The  "%i"  escape  has a cryptic output that is 11 letters long.
The general format is like the string YXcstpoguax,  where  Y  is
replaced  by the type of update being done, X is replaced by the
file-type, and the other letters represent attributes  that  may
be output if they are being modified.

The update types that replace the Y are as follows:

o      A  < means that a file is being transferred to the remote
       host (sent).

o      A > means that a file is being transferred to  the  local
       host (received).

o      A  c  means that a local change/creation is occurring for
       the item (such as the creation  of  a  directory  or  the
       changing of a symlink, etc.).

...
The file-types that replace the X are: f for a file, a d  for  a
directory,  an  L for a symlink, a D for a device, and a S for a
special file (e.g. named sockets and fifos).

The other letters in the string above  are  the  actual  letters
that  will be output if the associated attribute for the item is
being updated or a "." for no change.  Three exceptions to  this
are:  (1)  a newly created item replaces each letter with a "+",
(2) an identical item replaces the dots with spaces, and (3)  an
....

Немного критически, но, по крайней мере, он показывает сравнение базового каталога над ssh. Ура!

Ответ 6

Ответ на классический (System V Unix) будет dircmp dir1 dir2, который представляет собой оболочку script, которая будет отображать файлы, найденные либо в dir1, но не в dir2 или в dir2, но не в начале dir1 (первая страница вывода, из команды pr, поэтому с разбивкой по заголовкам), а затем сравнение каждого общего файла с анализом (то же самое, что и каталог, были наиболее распространенными).

Кажется, что он исчезает - у меня есть независимая реинтеграция его, если она вам нужна. Это не ракетостроение (cmp - ваш друг).