Como diferenciar vários arquivos entre diretórios?

19

Estou tentando encontrar diffs entre todos os arquivos com o mesmo nome em duas cópias de um diretório (por exemplo, um trabalho e um backup). Por exemplo, eu posso diffdois arquivos com o mesmo nome em ambos:

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

ou posso encontrar diferenças entre os diretórios:

> diff d1 d2

mas como posso encontrar diferenças apenas entre os *.cpparquivos?

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

parece não funcionar (por razões óbvias).

[Provavelmente é fácil resolver com loops, mas estou tentando encontrar uma maneira mais elegante]

ysap
fonte

Respostas:

13

Você pode usar um loop de shell que executa diff para cada arquivo, embora isso não ocorra nos casos em que o d2 contém um arquivo, mas o d1 não. Pode ser suficiente embora.

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

Ou tudo em uma linha:

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

A ${file##*/}peça é uma expansão de parâmetro especial.

Se a variável do arquivo contiver d1/hello.cpp, ela "${file##*/}"será expandida para hello.cpp(o valor do arquivo, mas com tudo, incluindo o último / removido).

Então "d2/${file##*/}", resultará d2/hello.cppe o comando diff resultante será, portanto,diff d1/hello.cpp d2/hello.cpp

Veja http://mywiki.wooledge.org/BashFAQ/100 para mais informações sobre manipulações de string no bash.

Em uma nota lateral, um sistema de controle de versão (como subversion, git, mercurial etc ...) tornaria esse tipo de diferença muito mais fácil.

Geirha
fonte
Eu acho que das duas ótimas respostas, isso é mais direto quando existem vários tipos de arquivo (embora eu tenha mencionado na pergunta que estou procurando uma solução sem loops), então aceitei. A adição adicionada é echo "${file##*/}";anterior ao diffcomando, para que se saiba quais arquivos estão realmente sendo comparados. Além disso, como mencionado na resposta de @ Rinzwind, esse método não cobre o caso em que a lista de arquivos não é exatamente a mesma nos dois diretórios.
ysap
52

diff -qr {DIR1} {DIR2} faz todos os arquivos nos dois diretórios.

  • q mostra apenas diferenças
  • rfaz recursivo. Deixe de fora se você não precisar disso

Você não pode dizer diffdiretamente para usar curingas, mas pode adicionar:

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

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

excluir arquivos. Portanto, se você deseja apenas *.cppo método mais fácil, crie um arquivo de texto que lista todos os arquivos que não são *.cpp. Você pode fazer isso com o seguinte comando: ls -I "*.cpp" > excluded_filesonde o -I "*.cpp"argumento ignora todos os arquivos .cpp. Observe que as aspas são necessárias.

Rinzwind
fonte
Simples e funciona perfeitamente.
Jose Gómez
4

Algum tempo depois de fazer a pergunta, descobri o meldutilitário diff e o uso desde então. Este é um ótimo programa baseado em GUI que torna a comparação e a mesclagem entre arquivos e diretório uma tarefa muito fácil. Faz comparações de duas ou três vias.

Especificamente, ele responde à minha pergunta original, pois mostra uma comparação com código de cores do conteúdo do diretório e permite comparar arquivos específicos clicando duas vezes no nome do arquivo.

Se é necessário mais do que uma comparação de três vias, também gvimdiff(com base no vimeditor) também é ótimo, oferecendo essa funcionalidade.

ysap
fonte
1

Existe uma solução leve para isso:

  1. Configure este pequeno plugin http://www.vim.org/scripts/script.php?script_id=5309
  2. Fazer diff dir1 dir2 | vim -R -no shell

Ele adicionará dobras e comparação lado a lado para arquivos alterados.

Yuriy Ershov
fonte