Porównuj rekurencyjnie dwa katalogi z różnicą -r bez danych wyjściowych w uszkodzonych linkach

38

Używam diff -r a bdo rekurencyjnego porównywania katalogów a i b . Często zdarza się jednak, że istnieją pewne niedziałających linków (te same linki zarówno A i b katalogów i wskazując tym samym, nieistniejących celów).

diff następnie wyświetla komunikaty o błędach dla tych przypadków i kończy działanie z niezerowym kodem wyjścia, jednak chciałbym, aby pozostało cicho i wychodziło z 0, ponieważ katalogi są takie same w mojej książce.

Jak mogę to zrobić?

Marcus Junius Brutus
źródło
Czy nadal chcesz porównywać dowiązania symboliczne (i identyfikować je jako równoważne, ale zepsute), czy też dopuszczalne jest ignorowanie wszystkich dowiązań symbolicznych podczas wykonywania tej różnicy?
ire_and_curses
w porównaniu i zidentyfikowane jako równoważne, nie dbam o to, czy są zepsute. Próbuję tylko sprawdzić, czy mój rsync działa.
Marcus Junius Brutus

Odpowiedzi:

24

W przypadku wersji 3.3 lub nowszej diffnależy skorzystać z --no-dereferenceopcji opisanej w odpowiedzi Pete'a Harlana .

Niestety starsze wersje diff nie obsługują ignorowania dowiązań symbolicznych :

Niektóre pliki nie są katalogami ani zwykłymi plikami: są to niezwykłe pliki, takie jak dowiązania symboliczne, specjalne pliki urządzeń, nazwane potoki i gniazda. Obecnie difftraktuje dowiązania symboliczne jak zwykłe pliki; traktuje inne pliki specjalne jak zwykłe pliki, jeśli są określone na najwyższym poziomie, ale po prostu zgłasza ich obecność podczas porównywania katalogów. Oznacza to, że patchnie mogą reprezentować zmian w takich plikach. Na przykład, jeśli zmienisz plik, na który wskazuje dowiązanie symboliczne, diffwyświetli różnicę między dwoma plikami, zamiast zmiany na dowiązanie symboliczne.

diffpowinien opcjonalnie zgłaszać zmiany w specjalnych plikach i patchpowinien zostać rozszerzony, aby zrozumieć te rozszerzenia.

Jeśli wszystko, czego chcesz, to zweryfikować rsync (i prawdopodobnie naprawić to, czego brakuje), możesz po prostu uruchomić polecenie rsync po raz drugi. Jeśli nie chcesz tego robić, podsumowanie katalogu może być wystarczające.

Jeśli naprawdę chcesz to zrobić diff, możesz findpominąć dowiązania symboliczne i uruchomić diff dla każdego pliku osobno. Zdać katalogów i B jako argumenty:

#!/bin/bash
# Skip files in $1 which are symlinks
for f in `find $1/* ! -type l`
do
    # Suppress details of differences
    diff -rq $f $2/${f##*/}
done

lub jako jedna linijka:

for f in `find a/* ! -type l`;do diff -rq $f b/${f##*/};done

To identyfikacji plików, które różnią się pod względem treści lub plików, które są w ale nie w b .

Uwaga:

  • ponieważ całkowicie pomijamy dowiązania symboliczne, nie zauważy to, jeśli nazwy dowiązań symbolicznych nie występują w b . Jeśli tego potrzebujesz, potrzebujesz drugiego hasła wyszukiwania, aby zidentyfikować wszystkie dowiązania symboliczne, a następnie jawnie sprawdzić ich obecność w b .
  • Dodatkowe pliki wb nie zostaną zidentyfikowane, ponieważ lista jest zbudowana z zawartości a . Prawdopodobnie nie jest to problem w twoim rsyncscenariuszu.
ire_and_curses
źródło
Proponowany skrypt nie działa rekurencyjnie w przypadku katalogów obecnych w katalogu „a” (ścieżki utworzone dla „b” przy użyciu b / $ {f ## *} są niepoprawne).
Marcus Junius Brutus
@MarcusJuniusBrutus - Tak, masz rację. Myślę, że rozwiązaniem jest usunięcie #, np. for f in Znajdź / *! -typ l ;do echo $f b/${f#*/};done. Jednak nie mam teraz czasu na przetestowanie tego. Daj mi znać, czy działa.
ire_and_curses
To jest lepiej jednak nadal bałagan z filepaths w wielu przypadkach. Wydaje się, że skrypt (z usuniętym #) musi zostać wywołany z katalogu bezpośrednio nad „a”, aby działać.
Marcus Junius Brutus
Ta odpowiedź staje się nieaktualny, gdy używa GNU diff 3,3 (patrz komentarze poniżej)
Bernd Gloss
Powyższy skrypt ma kilka problemów, ponieważ najpierw znajduje wszystkie nazwy plików i podaje je do rozszerzonej linii poleceń. (1) Odtąd będzie działać tylko z małymi zbiorami plików. (2) Żadna nazwa pliku ze znakiem specjalnym (nawet spacja) nie będzie przetwarzana. (3) Zawsze używaj $(xxx)zamiast backticks. Symetria wstecznych sprawia, że ​​są mniej czytelne i zapobiegają zagnieżdżaniu. Odnośnie 1 i 2 patrz stackoverflow.com/questions/11366184/…
Stéphane Gourichon
19

Od wersji 3.3 GNU diffnie obsługuje dereferencji dowiązań symbolicznych, ale porównuje ścieżki, na które wskazują.

Zainstaluj GNU diffutils> = 3.3 i skorzystaj z --no-dereferenceopcji; nie ma na to krótkiej opcji.

Diagnostyka będzie cicha, jeśli będzie równa lub:

Linki symboliczne /tmp/noderef/a/symlinki /tmp/noderef/b/symlinkróżnią się

Philippe De Muyter
źródło
Teraz, gdyby tylko pokazał zmiany treści, tak jakby dowiązanie symboliczne było zwykłym plikiem ...: - /
lindes
6

Możesz użyć nowszej wersji diff

W diffGNU diffutils3.3 zawiera --no-dereferenceopcję, która pozwala porównywać same dowiązania symboliczne, a nie ich cele. Informuje, czy się różnią, jest cicho, jeśli się zgadzają i nie obchodzi, czy są zepsute.

Nie wiem, kiedy dodano opcję; nie jest obecny w 2.8.1.

Pete Harlan
źródło
Mogę potwierdzić, że nie istnieje w diffutils (GNU diffutils) 3.2
Elder Geek