Como posso fazer com que 'diff -X' ignore caminhos específicos e não nomes de arquivos?

29

Fazendo: diff -r -X <ignore-list> <src-dir> <dest-dir>

parece não fazer diffentradas de ignorar <ignore-list>se forem do formulário <dir>/<file>.

Entradas do formulário <file>, no entanto, são consideradas. Esse é um problema, pois eu posso ter vários arquivos nomeados <file>em subdiretórios diferentes, alguns dos quais não quero que sejam ignorados.

Também não parece haver muita informação sobre a sintaxe de padrão na página de manual diff. Pelo que sei, é apenas o nome base de um arquivo que é considerado pelo diff (veja http://forums.gentoo.org/viewtopic-t-889788-start-0.html se você estiver interessado).

Cinza
fonte
homem, diff's --excludeopção é tão merda ...
Elouan Keryell-Even

Respostas:

30

Os diretórios de listagem devem funcionar; por exemplo, aqui está o que eu usei em um script (assumindo o gnu diff),

diff -r \
   --exclude="*~" \
   --exclude=".svn" \
   --exclude=".git" \
   --exclude="*.zip*" \
   --exclude="*.gz" \
   --exclude="*.tar" \
   ...etc

... que ignora o conteúdo de .svne .gitdirs, mas também arquivos individuais chamados *.zip/ *.gz/ etc.

Editar: para filtrar caminhos do formulário, dir_a/file1mas ainda diffarquivos com o mesmo nome de base, como dir_b/file1ou dir_a/b/file1, uma lista de arquivos diffa ser gerada (por exemplo, usando find) e o arquivo a ser comparado derivado desses caminhos; por exemplo, dado

$ find ONE TWO -type f -print 
ONE/a/1.txt
ONE/a/2.txt
ONE/a/b/2.txt
TWO/a/1.txt
TWO/a/2.txt
TWO/a/b/2.txt

você gera a lista de arquivos para comparar, excluindo, por exemplo, */a/2.txtmas ainda comparando outros arquivos nomeados 2.txt. Apenas "encontre" todos os arquivos, exceto ONE/a/2.txt(um regexp também pode ser usado aqui, como .*/a/2.txt)

$ find ONE -type f \( ! -regex 'ONE/a/2.txt' \) \
    -exec bash -c 'diff -q "${1}" "${2/ONE/TWO}"' - {} {} \;  

que na verdade ignora ONE/a/2.txt(e TWO/a/2.txt), mas ainda compara os outros arquivos chamados 2.txt:

diff -q ONE/a/1.txt TWO/a/1.txt
diff -q ONE/a/b/2.txt TWO/a/b/2.txt

Editar: Ou, mais divertido find(diversão adicional deixada como exercício para o leitor), selecione os arquivos ou diretórios a serem excluídos e depois difftodo o resto:

$ find ONE \( -regex 'ONE/a/2.txt' -o -name b  -prune \)  \
    -o -type f -exec bash -c 'echo diff -q "${1}" "${2/ONE/TWO}"' - {} {} \

O exemplo acima exclui o arquivo específico "{top} /a/2.txt", qualquer diretório chamado "b" e todo o resto é diferente. (Em vez de simples " -name b", você também pode usar " -regex '.*/b'" - observe, não há "/" à direita).

Michael
fonte
2
Obrigado, mas acho que você está perdendo o objetivo. O único suporte que parece existir é quando você usa um 'nome-base'. Esse poderia ser o nome de um diretório ou arquivo. Em ambos os casos, o diff ignora o que você pediu. O problema surge quando você usa caminhos. Por exemplo, não consigo obter o diff para ignorar / an / absolute / path / to / a / file ou ./a/relative/path/to/a/file.
Ash
2
diff --exclude = "/ isto / específico / arquivo / isso / im / explicitamente / suplicando / você / que / ignore". Isso não vai funcionar.
Ash
3
correto, os excludepadrões são comparados com o nome base dos arquivos (conforme gnu.org/software/diffutils/manual/html_node/… ); caminhos não funcionarão (como em foo/bar.txt). Para fazer isso, você provavelmente precisará executar findpara gerar a lista de nomes de arquivos e derivar o caminho para o arquivo comparar.
22613 Michael
resposta atualizado para incluir exemplo excluindo caminhos de arquivo a partir do diff, em vez de apenas usandobasename
michael
Ok, entendo o que você está propondo, mas parece haver um problema. Eu preciso considerar diretórios também, não apenas arquivos (ou seja, -type f). Agora, enquanto você ainda pode remover determinados arquivos usando o regexp find, se a entrada diffcontiver um diretório, ela analisará e comparará os arquivos dentro desse diretório e alguns desses arquivos precisarão ser ignorados ... de volta à estaca 1.
Ash
2

Como tive o mesmo problema, criei um patch para diff . O patch ainda não foi aceito, mas você pode criar sua própria versão diffcom o patch ou instalar no Arch Linux com um pacote AUR .

Aqui está o diffpatch.

Dave Parrish
fonte
1

Para excluir o diretório directory/sub-directory, eu uso

diff -r <src-dir> <dest-dir> | grep -v directory/sub-directory

No entanto, embora deva funcionar para uma única exclusão, não deve ser possível para uma longa lista de ignorados como você possui.

Elouan Keryell-Even
fonte
-2
$ diff -rq foo.orig foo | grep -vP 'ignore1/|exclude2/' | awk '{print $2}' | cut -d'/' -f2- | xargs -I{} diff -u foo.orig/{} foo/{}
vern
fonte
1
Embora isso possa responder à pergunta, seria uma resposta melhor se você pudesse fornecer alguma explicação para isso.
DavidPostill