Como você difere um diretório apenas para arquivos de um tipo específico?

88

Eu tenho uma pergunta sobre o comando diff, se eu quiser um diff de diretório recursivo, mas apenas para um tipo de arquivo específico, como fazer isso?

Tentei usar a opção de exclusão, mas só consigo usar um padrão:

$ diff /destination/dir/1 /destination/dir/2 -r -x *.xml

com o comando só posso excluir tipo de arquivo xml, mesmo que haja arquivos no tipo de imagem pasta ( png, gif, jpg), txt, php, etc

como diferenciar apenas certos tipos de arquivo.

de_3
fonte
1
stackoverflow.com/q/10131908/2707864
sancho.s ReinstateMonicaCellio
Então você está tentando comparar arquivos de um tipo específico ou excluí-los da comparação? A pergunta não se correlaciona com a descrição ..
def

Respostas:

98

Você pode especificar -xmais de uma vez.

diff -x '*.foo' -x '*.bar' -x '*.baz' /destination/dir/1 /destination/dir/2

Na seção Comparando diretórios de info diff(no meu sistema, tenho que fazer info -f /usr/share/info/diff.info.gz):

Para ignorar alguns arquivos ao comparar diretórios, use a opção '-x PATTERN' ou '--exclude = PATTERN'. Esta opção ignora quaisquer arquivos ou subdiretórios cujos nomes de base correspondam ao padrão de shell PATTERN. Ao contrário do shell, um ponto no início da base de um nome de arquivo corresponde a um curinga no início de um padrão. Você deve colocar PATTERN entre aspas para que o shell não o expanda. Por exemplo, a opção -x '*. [Ao]' ignora qualquer arquivo cujo nome termine com '.a' ou '.o'.

Esta opção se acumula se você especificá-la mais de uma vez. Por exemplo, usando as opções -x 'RCS' -x '*, v' ignora qualquer arquivo ou subdiretório cujo nome de base seja 'RCS' ou termine com ', v'.

Dennis Williamson
fonte
O meu (ubuntu 10.04) não tem essas linhas. Eu também tentei e não funcionou. Eu acho que esta é uma nova versão.
alumi
22

Retirado de (uma versão da) página de manual:

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

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

Portanto, parece que -xaceita apenas um padrão conforme você relata, mas se você colocar todos os padrões que deseja excluir em um arquivo (provavelmente um por linha), poderá usar o segundo sinalizador assim:

$ diff /destination/dir/1 /destination/dir/2 -r -X exclude.pats

onde exclude.pats é:

*.jpg
*.JPG
*.xml
*.XML
*.png
*.gif
Jamesbtate
fonte
4
Você pode encontrar todas as extensões de arquivo em sua pasta, exceto a extensão <my-ext> com a seguinte linha de comando:find . -type f -not -name '*.<my-ext>' | xargs -I% basename '%' | awk -F . 'NF > 1 { print "*." $NF}; NF == 1 { print $NF }' | sort | uniq > exclude.pats
John
Gostaria de ter notado o comentário de John antes, mas no macOs / bash cheguei a uma solução semelhante para produzir o arquivo de exclusão com vários padrões para manter: find . -not -name "*.c" -and -not -name "*.h" -and -type f -print0 | xargs -0 basename | grep -E '.*\..+' | sed 's/\./\//g' | xargs basename | xargs printf '*.%s\n' | sort | uniq > X-FILEquero acreditar que isso ajuda, talvez no Linux também. (Neste exemplo, um único -name "*.[ch]"está correto, mas não é muito ilustrativo)
eruve
16

Você também pode usar find com -exec para chamar diff:

cd /destination/dir/1
find . -name *.xml -exec diff {} /destination/dir/2/{} \;
Alex Harui
fonte
7

A falta de um complementar --include ....

Podemos fazer uma solução alternativa, um arquivo de exclusão com todos os arquivos, exceto o que queremos incluir. Assim, criamos file1com um find todos os arquivos que não têm extensões que queremos incluir, sedpegamos o nome do arquivo e é apenas:

diff --exclude-from=file1  PATH1/ PATH2/

Por exemplo:

find  PATH1/ -type f | grep --text -vP "php$|html$" | sed 's/.*\///' | sort -u > file1 
diff PATH1/ PATH2/ -rq -X file1 
Sérgio
fonte
One-liner super útil, thx. No Mac OSX, o grep é um pouco diferente e se torna find PATH1/ -type f | grep --text -v -e "php$" -e html$" | sed 's/.*\///' | sort -u > file1 diff PATH1/ PATH2/ -rq -X file1
mmacvicar
3

Usei o seguinte comando para encontrar o diff de todos os *.tmplarquivos entre DIR1e DIR2. No meu caso, isso não rendeu nenhum falso positivo, mas pode render para você, dependendo do conteúdo do seu DIRS.

diff --brief DIR1 DIR2 | grep tmpl

Mikhail Golubitsky
fonte
2

Se você deseja diferenciar as fontes e mantê-lo simples:

diff -rqx "*.a" -x "*.o" -x "*.d" ./PATH1 ./PATH2 | grep "\.cpp " | grep "^Files"

Remova o último grep se quiser obter os arquivos que existem em apenas um dos caminhos.

Alex
fonte
Eu gosto de simplicidade :-) Em alemão, mude grep "^Files"paragrep "^Dateien"
Erich Kuester
2

Caso você ache conveniente, você pode usar o seguinte Makefile. Basta executar: "make patch"

#Makefile for patches

#Exlude following file endings
SUFFIX += o
SUFFIX += so
SUFFIX += exe
SUFFIX += pdf
SUFFIX += swp

#Exlude following folders
FOLDER += bin
FOLDER += lib
FOLDER += Image
FOLDER += models

OPTIONS = Naur

patch: 
    rm test.patch
    diff -$(OPTIONS) \
    $(foreach element, $(SUFFIX) , -x '*.$(element)') \
    $(foreach element, $(FOLDER) , -x '$(element)*') \
        org/ new/ > test.patch  

unpatch: 
    rm test.unpatch
    diff -$(OPTIONS) \
    $(foreach element, $(SUFFIX) , -x '*.$(element)') \
    $(foreach element, $(FOLDER) , -x '$(element)*') \
    new/ org/ > test.unpatch
Rafiz
fonte
1

A falta de um complemento --include torna necessário o uso de padrões heurísticos complicados como

*.[A-Zb-ik-uw-z]*

para encontrar (principalmente) arquivos java!

Jerry Miller
fonte
0

Embora não evite o real diffde outros arquivos, se seu objetivo é produzir um arquivo de patch, ou semelhante, você pode usar filterdiffdo patchutilspacote, por exemplo, para corrigir apenas suas .pyalterações:

diff -ruNp /path/1 /path/2 | filterdiff -i "*.py" | tee /path/to/file.patch
Cez
fonte