Como comparar arquivos com os mesmos nomes em dois diretórios diferentes usando um shell script

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

  •  02-07-2019
  •  | 
  •  

Pergunta

Antes de passar para usar o SVN, eu utilizado para gerir o meu projeto, basta manter um diretório /develop/ e editando e testando arquivos lá, então movê-los para o diretório /main/. Quando eu decidi me mudar para SVN, eu precisava ter certeza de que os diretórios eram de fato em sincronia.

Então, o que é uma boa maneira de escrever um script shell [festa] para arquivos recursivamente comparar com o mesmo nome em dois diretórios diferentes?

Nota: Os nomes de diretório usados ??acima são apenas para amostra. Eu não recomendo guardar o seu código no nível superior:.)

Foi útil?

Solução

O comando diff tem uma opção -r para diretórios recursivamente comparar:

diff -r /develop /main

Outras dicas

diff -rqu /develop /main

Ele só vai te dar um resumo das alterações que maneira :)

Se você quiser ver apenas new / faltando arquivos

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

Se você quiser levá-los a nu:

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

O diff que tenho disponível permite diferenças recursiva:

diff -r main develop

Mas com um shell script:

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

[Li algures que responder às suas próprias perguntas é OK, então aqui vai :)]

Eu tentei isso, e funcionou muito bem

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

Você pode optar por comparar apenas arquivos específicos [por exemplo, apenas os .php] editando a linha acima como

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

Quaisquer outras ideias?

aqui é um exemplo de um script (um tanto confuso) da mina, dircompare.sh , que irá:

  • arquivos de ordenação e diretórios em matrizes dependendo de qual diretório eles ocorrem em (ou ambos), em duas passagens recursiva
  • Os arquivos que ocorrem em ambos os diretórios, são classificadas novamente em duas matrizes, dependendo se diff -q determina se eles diferem ou não
  • para os arquivos que reivindicações diff são iguais, mostram e comparam timestamps

A esperança pode ser encontrada útil - Felicidades

EDIT2: ( Na verdade, ele funciona bem com arquivos remotos - o problema foi não tratada sinal Ctrl-C durante uma operação de comparação entre arquivos local e remoto, que pode demorar um pouco; script agora atualizado com uma armadilha para alça que - no entanto, deixando a edição anterior abaixo para referência ):

EDIT: ... exceto parece falhar o meu servidor para um diretório ssh remoto (que eu tentei usar mais ~/.gvfs) ... Portanto, este não é bash mais, mas um eu acho alternativa é usar rsync, aqui está um exemplo:

$ # 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
...

Note que:

  • Para obter o acima, você não deve esquecer de fuga barras / no final de nomes de diretório em rsync
  • --dry-run - simular Só, Não arquivos de atualização / transferência
  • -r - recurse em diretórios
  • -v - verboso (mas não relacionado ao arquivo muda info)
  • --cvs-exclude - ignorar arquivos .svn
  • -i - "--itemize-changes: saída de uma mudança-resumo para todas as atualizações"

Aqui está um breve trecho de man rsync que explica as informações mostradas por -i (por exemplo, as cordas >f.st...... acima):

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
....

Um pouco enigmática, na verdade -, mas pelo menos mostra a comparação de diretório básica sobre ssh. Felicidades!

A resposta clássica (System V Unix) seria dircmp dir1 dir2, que era um shell script que iria listar os arquivos encontrados em qualquer dir1, mas não dir2 ou em dir2, mas não dir1 no início (primeira página de saída, a partir do comando pr , de modo paginado com títulos), seguido por uma comparação de cada arquivo comum com uma análise (mesmo, diferente, diretório foram os resultados mais comuns).

Este parece ser em processo de desaparecimento - Eu tenho uma reimplementação independente dela disponível se você precisar dele. Não é ciência de foguetes (cmp é seu amigo).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top