Jak porównać katalog dla plików tylko określonego typu?

88

Mam pytanie dotyczące polecenia diff, jeśli chcę rekursywnego porównania katalogu, ale tylko dla określonego typu pliku, jak to zrobić?

Próbowałem użyć opcji wykluczania, ale mogę użyć tylko jednego wzorca:

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

z poleceniem mogę tylko wyklucza typ pliku xml, chociaż istnieją pliki w folderze typu obrazu ( png, gif, jpg) txt, phpitp

jak porównać tylko niektóre typy plików.

de_3
źródło
1
stackoverflow.com/q/10131908/2707864
sancho.s ReinstateMonicaCellio
Więc czy próbujesz porównać pliki określonego typu, czy też wykluczyć te pliki z porównywania? Pytanie nie koreluje z opisem ...
def.

Odpowiedzi:

97

Możesz podać -xwięcej niż jeden raz.

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

Z sekcji Porównanie katalogów info diff(w moim systemie muszę to zrobić info -f /usr/share/info/diff.info.gz):

Aby zignorować niektóre pliki podczas porównywania katalogów, użyj opcji „-x WZORZEC” lub „--exclude = WZÓR”. Ta opcja ignoruje wszystkie pliki lub podkatalogi, których nazwy podstawowe pasują do wzorca powłoki PATTERN. W przeciwieństwie do powłoki, kropka na początku podstawy nazwy pliku jest zgodna z symbolem wieloznacznym na początku wzorca. PATTERN należy ująć w cudzysłowy, aby powłoka go nie rozszerzyła. Na przykład opcja -x '*. [Ao]' ignoruje każdy plik, którego nazwa kończy się na '.a' lub '.o'.

Ta opcja kumuluje się, jeśli określisz ją więcej niż raz. Na przykład użycie opcji -x 'RCS' -x '*, v' ignoruje każdy plik lub podkatalog, którego nazwa podstawowa to 'RCS' lub kończy się na ', v'.

Wstrzymano do odwołania.
źródło
Mój (ubuntu 10.04) nie ma tych wierszy. Próbowałem też i nie udało się. Myślę, że to nowa wersja.
alumi
22

Zaczerpnięte z (wersji) strony podręcznika:

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

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

Wygląda więc na to, że -xraport akceptuje tylko jeden wzorzec, ale jeśli umieścisz w pliku wszystkie wzorce, które chcesz wykluczyć (prawdopodobnie jeden w każdym wierszu), możesz użyć drugiej flagi w następujący sposób:

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

gdzie exclude.pats to:

*.jpg
*.JPG
*.xml
*.XML
*.png
*.gif
jamesbtate
źródło
4
Można znaleźć wszystkie rozszerzenia plików w folderze z wyjątkiem <my-ext> rozszerzenie z następującym wierszu poleceń: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
Żałuję, że nie zauważyłem komentarza Johna wcześniej, ale w przypadku macOs / bash doszedłem do podobnego rozwiązania, aby utworzyć plik wykluczeń z kilkoma wzorcami do zachowania: 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-FILEchcę wierzyć, że to pomaga, być może także w Linuksie. (W tym przykładzie singiel -name "*.[ch]"jest w porządku, ale nie jest zbyt ilustracyjny)
eruve
16

Możesz także użyć find z -exec, aby wywołać diff:

cd /destination/dir/1
find . -name *.xml -exec diff {} /destination/dir/2/{} \;
Alex Harui
źródło
7

Brak komplementarności - obejmują ....

Możemy zastosować jedno obejście, plik wykluczeń ze wszystkimi plikami, ale to, co chcemy, dołączyć. Więc tworzymy file1za pomocą funkcji find wszystkie pliki, które nie mają rozszerzeń, które chcemy uwzględnić, sedprzechwytujemy nazwę pliku i po prostu:

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

Na przykład:

find  PATH1/ -type f | grep --text -vP "php$|html$" | sed 's/.*\///' | sort -u > file1 
diff PATH1/ PATH2/ -rq -X file1 
Sérgio
źródło
Super przydatna jedna linijka, dzięki. W systemie Mac OSX grep jest nieco inny i staje się find PATH1/ -type f | grep --text -v -e "php$" -e html$" | sed 's/.*\///' | sort -u > file1 diff PATH1/ PATH2/ -rq -X file1
mmacvicar
3

Użyłem następującego polecenia, aby znaleźć różnice wszystkich *.tmplplików między DIR1a DIR2. W moim przypadku nie przyniosło to żadnych fałszywych alarmów, ale może to być dla Ciebie, w zależności od zawartości Twoich DIRS.

diff --brief DIR1 DIR2 | grep tmpl

Michaił Golubitsky
źródło
2

Jeśli uznasz to za wygodne, możesz użyć następujących Makefile. Po prostu uruchom: „utwórz poprawkę”

#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
źródło
1

Brak komplementarnego - include, sprawia, że ​​konieczne jest stosowanie tak zawiłych wzorców heurystycznych, jak

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

znaleźć (głównie) pliki java!

Jerry Miller
źródło
1

Jeśli chcesz zróżnicować źródła i zachować prostotę:

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

Usuń ostatni plik grep, jeśli chcesz pobrać pliki, które istnieją tylko w jednej ze ścieżek.

Alex
źródło
0

Chociaż nie pozwala to uniknąć diffinnych plików, jeśli Twoim celem jest stworzenie pliku łatki lub podobnego, możesz użyć filterdiffz patchutilspakietu, np. Do załatania tylko swoich .pyzmian:

diff -ruNp /path/1 /path/2 | filterdiff -i "*.py" | tee /path/to/file.patch
Cez
źródło