Come si differenzia una directory solo per file di un tipo specifico?


88

Ho una domanda sul comando diff se voglio un diff di directory ricorsivo ma solo per un tipo di file specifico, come farlo?

Ho provato a utilizzare l'opzione di esclusione ma posso utilizzare solo un pattern:

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

con il comando posso escludere solo tipo di file XML, anche se ci sono file nella cartella di tipo di immagine ( png, gif, jpg), txt, php, ecc

come diffondere solo alcuni tipi di file.



Quindi stai cercando di diffondere file di tipo specifico o di escludere quei file dalla differenza? La domanda non è correlata alla descrizione ..
def

Risposte:


97

Puoi specificare -xpiù di una volta.

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

Dalla sezione Confronto delle directory di info diff(sul mio sistema, devo fare info -f /usr/share/info/diff.info.gz):

Per ignorare alcuni file durante il confronto delle directory, utilizzare l'opzione "-x PATTERN" o "--exclude = PATTERN". Questa opzione ignora i file o le sottodirectory i cui nomi di base corrispondono al pattern di shell PATTERN. A differenza della shell, un punto all'inizio della base di un nome file corrisponde a un carattere jolly all'inizio di un pattern. È necessario racchiudere PATTERN tra virgolette in modo che la shell non la espanda. Ad esempio, l'opzione -x '*. [Ao]' ignora qualsiasi file il cui nome termina con '.a' o '.o'.

Questa opzione si accumula se viene specificata più di una volta. Ad esempio, utilizzando le opzioni -x 'RCS' -x '*, v' ignora qualsiasi file o sottodirectory il cui nome di base è 'RCS' o termina con ', v'.


Il mio (ubuntu 10.04) non ha queste righe. Ho anche provato e non ha funzionato. Immagino che questa sia una nuova versione.
alumi

22

Tratto da (una versione della) pagina man:

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

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

Quindi sembra che -xaccetti solo un pattern mentre segnali, ma se metti tutti i pattern che vuoi escludere in un file (presumibilmente uno per riga) potresti usare il secondo flag in questo modo:

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

dove exclude.pats è:

*.jpg
*.JPG
*.xml
*.XML
*.png
*.gif

4
Puoi trovare tutte le estensioni di file all'interno della tua cartella ad eccezione dell'estensione <my-ext> con la seguente riga di 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

Vorrei aver notato prima il commento di John, ma su macOs / bash sono arrivato a una soluzione simile per produrre il file di esclusione con diversi pattern da mantenere: 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-FILEvoglio credere che aiuti, forse anche su Linux. (In questo esempio un singolo -name "*.[ch]"va bene, ma non è molto illustrativo)
eruve

16

Puoi anche usare find con -exec per chiamare diff:

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

7

La mancanza di un complementare --include ....

Possiamo fare una soluzione alternativa, un file di esclusione con tutti i file ma ciò che vogliamo includere. Quindi creiamo file1con una ricerca tutti i file che non hanno estensioni che vogliamo includere, sedcatturiamo il nome del file ed è solo:

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

Per esempio:

find  PATH1/ -type f | grep --text -vP "php$|html$" | sed 's/.*\///' | sort -u > file1 
diff PATH1/ PATH2/ -rq -X file1 

Super utile one-liner, thx. Su Mac OSX grep è leggermente diverso e diventa find PATH1/ -type f | grep --text -v -e "php$" -e html$" | sed 's/.*\///' | sort -u > file1 diff PATH1/ PATH2/ -rq -X file1
mmacvicar

3

Ho usato il seguente comando per trovare il diff di tutti i *.tmplfile tra DIR1e DIR2. Nel mio caso questo non ha prodotto falsi positivi, ma potrebbe esserlo per te, a seconda del contenuto del tuo DIRS.

diff --brief DIR1 DIR2 | grep tmpl


2

Nel caso in cui lo trovi conveniente, puoi utilizzare quanto segue Makefile. Esegui: "crea 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

1

La mancanza di un --include complementare rende necessario usare schemi euristici contorti come

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

per trovare (principalmente) file java!


1

Se vuoi differenziare le fonti e mantenerlo semplice:

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

Rimuovi l'ultimo grep se vuoi ottenere i file che esistono solo in uno dei percorsi.


0

Sebbene non eviti l'effettivo diffdi altri file, se il tuo obiettivo è produrre un file di patch, o simile, puoi utilizzare filterdiffdal patchutilspacchetto, ad esempio per applicare solo le .pymodifiche:

diff -ruNp /path/1 /path/2 | filterdiff -i "*.py" | tee /path/to/file.patch
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.