Jak sprawić, by „diff -X” ignorował określone ścieżki, a nie nazwy plików?

29

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

nie wydaje się diffignorować wpisów, <ignore-list>jeśli są one w formie <dir>/<file>.

Wpisy formularza <file> są jednak brane pod uwagę. Jest to problem, ponieważ mogę mieć wiele plików o <file>różnych nazwach w różnych podkatalogach, z których niektórych nie chcę ignorować.

Wydaje się, że na stronie podręcznika nie ma zbyt wielu informacji dotyczących składni wzorców diff. Z tego, co mogę powiedzieć, to tylko podstawowa nazwa pliku, który jest rozważany przez diff (patrz http://forums.gentoo.org/viewtopic-t-889788-start-0.html, jeśli jesteś zainteresowany).

Popiół
źródło
człowiek, diffjest --excludeopcja jest tak gówniany ...
Elouan Keryell-Nawet

Odpowiedzi:

30

Listy katalogów powinny działać; np. oto, czego użyłem w skrypcie (zakładając, że gnu diff),

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

... która ignoruje zawartość .svni .gitkatalogi, ale także pojedyncze pliki o nazwie *.zip/ *.gz/ etc.

Edycja: W celu filtrowania ścieżek formularza, dir_a/file1ale nadal diffplików o tej samej nazwie basename, takich jak dir_b/file1lub dir_a/b/file1, diffnależy wygenerować listę plików do wygenerowania (na przykład przy użyciu find), a plik do porównania wyprowadzić z tych ścieżek; np. dane

$ 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

generujesz listę plików do porównania, wyłączając na przykład, */a/2.txtale nadal porównując inne pliki o nazwie 2.txt. Po prostu „znajdź” wszystkie pliki oprócz ONE/a/2.txt(można również użyć wyrażenia regularnego, np. .*/a/2.txt)

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

co w efekcie ignoruje ONE/a/2.txt(i TWO/a/2.txt), ale wciąż porównuje inne pliki o nazwie 2.txt:

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

Edycja: Lub, więcej zabawy z find(dodatkowa zabawa pozostała jako ćwiczenie dla czytelnika), wybierz pliki lub katalogi do wykluczenia, a następnie diffwszystko inne:

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

Powyższy przykład wyklucza konkretny plik „{top} /a/2.txt”, dowolny katalog o nazwie „b” i wszystko inne jest odmienne. (Zamiast prostego „ -name b” można również użyć „ -regex '.*/b'” - uwaga, bez końcowego „/”.)

Michał
źródło
2
Dzięki, ale myślę, że nie rozumiesz. Wydaje się, że jedynym wsparciem jest użycie „podstawowej nazwy”. Może to być nazwa katalogu lub pliku. W obu przypadkach diff ignoruje to, o co prosiłeś. Problem powstaje podczas korzystania ze ścieżek. Na przykład nie mogę zmusić diff do ignorowania / an / absolut / ścieżka / do / a / pliku lub ./a/relative/path/to/a/file.
Ash
2
diff --exclude = "/ this / specific / file / that / im / jawnie / pleading / you / to / ignore". To nie zadziała.
Ash
3
poprawne, excludewzorce są dopasowane do nazwy pliku (zgodnie z gnu.org/software/diffutils/manual/html_node/… ); ścieżki nie będą działać (jak w foo/bar.txt). Aby to zrobić, prawdopodobnie będziesz musiał uruchomić, findaby wygenerować listę nazw plików i uzyskać ścieżkę do pliku do porównania.
Michael
zaktualizowana odpowiedź zawierająca przykład wykluczający ścieżki plików z diffzamiast zamiastbasename
Michael
OK, rozumiem, co proponujesz, ale wydaje się, że jest problem. Muszę również wziąć pod uwagę katalogi, a nie tylko pliki (tj. -Type f). Teraz, mimo że nadal możesz przycinać niektóre pliki za pomocą wyrażenia regularnego z find, jeśli dane wejściowe do diffzawierają katalog, przejdzie i porówna pliki w tym katalogu, a niektóre z tych plików mogą wymagać zignorowania ... więc jesteś powrót do kwadratu 1.
Ash
2

Miałem ten sam problem, więc utworzyłem łatkę do diff. Poprawka nie została jeszcze zaakceptowana, ale możesz zbudować własną wersję diffz łatką lub zainstalować na Arch Linux z pakietem AUR .

Tutaj jest diffpoprawka.

Dave Parrish
źródło
1

Aby wykluczyć katalog directory/sub-directory, używam

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

Jednak chociaż powinno to działać dla pojedynczego wykluczenia, nie powinno być możliwe stosowanie długiej listy ignorowanych, tak jak masz.

Elouan Keryell-Even
źródło
-2
$ diff -rq foo.orig foo | grep -vP 'ignore1/|exclude2/' | awk '{print $2}' | cut -d'/' -f2- | xargs -I{} diff -u foo.orig/{} foo/{}
Vern
źródło
1
Chociaż może to odpowiedzieć na pytanie, lepszym rozwiązaniem byłoby wyjaśnienie, dlaczego tak się dzieje.
DavidPostill