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

StackOverflow https://stackoverflow.com/questions/119788

  •  02-07-2019
  •  | 
  •  

Вопрос

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

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

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

Это было полезно?

Решение

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

diff -r /develop /main

Другие советы

diff -rqu /develop /main

Таким образом, вы получите только сводку изменений :)

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

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

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

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

Имеющийся у меня diff допускает рекурсивные различия:

diff -r main develop

Но с помощью сценария оболочки:

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

[Я где-то читал, что отвечать на свои вопросы можно, так что вот :) ]

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

[/]$ 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

Есть еще идеи?

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

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

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

РЕДАКТИРОВАТЬ2:(На самом деле, с удаленными файлами он работает нормально - проблема заключалась в необработанном сигнале Ctrl-C во время операции сравнения между локальным и удаленным файлом, которая может занять некоторое время;скрипт теперь обновлен с помощью ловушки, позволяющей справиться с этим, однако предыдущее редактирование ниже оставлено для справки.):

РЕДАКТИРОВАТЬ:...за исключением того, что мой сервер, похоже, приводит к сбою из-за удаленного каталога ssh (который я пытался использовать через ~/.gvfs)...Так что это не bash больше, но альтернативой, я думаю, является использование rsync, вот пример:

$ # get example revision 4527 as testdir1
$ svn co https://openbabel.svn.sf.net/svnroot/openbabel/openbabel/trunk/data@4527 testdir1

$ # get earlier example revision 2729 as testdir2
$ svn co https://openbabel.svn.sf.net/svnroot/openbabel/openbabel/trunk/data@2729 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.Ваше здоровье!

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top