[+] bash - porównywanie katalogów za pomoc

Potrzebujesz pomocy z C, C++, perl, python, itp.
RRH
Beginner
Posty: 140
Rejestracja: 27 października 2006, 21:09

[+] bash - porównywanie katalogów za pomocą diff

Post autor: RRH »

Witam serdecznie!

Piszę sobie prościutki skrypt do tworzenia kopii zapasowej, ale z racji mojej maluteńkiej wiedzy na temat basha napotykam na problemy.
Stanąłem na etapie porównywania dwóch katalogów. Niby rezultat jest dobry, ale nie wiem czy robię to dobrze i czy może istnieje lepszy sposób na dokonanie tego.
Ale od początku.

Na początku zapisuje strukturę drzewa jednego i drugiego katalogu do osobnych plików, nazwijmy je: katalog1Zaw i katalog2Zaw.

plik katalog1Zaw

Kod: Zaznacz cały

plik01
plik02
plik03
katalog/plik01
katalog/plik02
katalog/plik03
plik katalog2Zaw

Kod: Zaznacz cały

katalog/plik01
katalog/plik02
plik01
plik03
Jakimś cudem udało mi się porównać oba pliki, takim sposobem:

Kod: Zaznacz cały

diff --change-group-format=' %<' katalog1Zaw katalog2Zaw
wynik jest taki:

Kod: Zaznacz cały

 plik01
plik02
plik03
katalog/plik01
katalog/plik02
katalog/plik03
Jeżeli po lewej kolumnie (kolumny są rozdzielone spacją) nic nie ma lub jest, to pliki się powtarzają.
Jeżeli po w prawej kolumnie jest nazwa pliku, to należy przekopiować ten plik do katalogu drugiego.

Napisałem jakimś cudem, bo za nic nie mogłem rozgryźć, co do czego służy w diff.
Istnieją formaty grupy i formaty linii. I pomimo czytania podręcznika systemowego, nie potrafię poprawnie posługiwać się new-group-format, old-group-format, changed-group-format, unchanged-group-format.
W sieci też nie znalazłem żadnych wyjaśnień.
Dlatego pytam się, czy istnieje inny sposób na wyświetlenie różnicy w plikach w takim formacie, jaki przedstawiłem.
Fajnie byłoby, gdyby znalazła się osoba, która w prosty sposób wytłumaczyłaby mi działanie tego potworka, którego przypadkiem napisałem.

To jedna sprawa. Druga jak zapisać ten wynik, aby był bardziej zrozumiały - aby wyglądał np. tak:

Kod: Zaznacz cały

[katalog1]     [katalog2]           [kopiowanie]
----------------------------------------------
plik01                                   TAK
plik02                                    NIE
plik03                                    NIE
katalog/plik01                        NIE
katalog/plik02                        NIE
katalog/plik03                        TAK
To znaczy, jak zapisać w bashu:
- jeżeli nic nie pisze w lewej kolumnie, skopiuj np. plik01 do katalogu2
- jeżeli jest nazwa pliku w lewej kolumnie, nie nie kopiuj.
Podejrzewam, że aby uzyskać takie kolumny i informacje (TAK, NIE) trzeba użyć sed, ale problem w tym, że nie wiem z jakiej strony się za to zabrać.

Problem dla mnie trudny, ale wierzę, że dla wielu z Was banalny.
Jeżeli znajdzie się osoba, która poświęci swój cenny czas za zerknięcie na ten problem, to będę ogromnie wdzięczny.

Pozdrawiam i liczę na Wasz odzew.
salmon
Beginner
Posty: 296
Rejestracja: 12 października 2007, 23:28
Lokalizacja: Gliwice/Bielsko-Biała

Post autor: salmon »

Po pierwsze, w obu plikach nazwy musisz mieć w tej samej kolejności.
Może mały przykładzik:
Masz dwa pliki:
1

Kod: Zaznacz cały

plik1
plik2
katalog/plik1
katalog/plik2
2

Kod: Zaznacz cały

plik1
katalog/plik2
katalog/plik3
katalog/plik5
Zakładamy, że plik 1 jest aktualnym spisem katalogu, a 2 tym z kopi zapasowej. Chcesz więc wiedzieć co powinieneś dodać lub usunąć z pliku 2. Wykonujesz

Kod: Zaznacz cały

diff 2 1
a na wyjściu masz to:

Kod: Zaznacz cały

1a2,3
> plik2
> katalog/plik1
3,4d4
< katalog/plik3
< katalog/plik5

Opis wyjścia:

Kod: Zaznacz cały

1a2,3
> plik2
dodano plik 2

Kod: Zaznacz cały

> katalog/plik1
dodano kataolog/plik2

Kod: Zaznacz cały

3,4d4
< katalog/plik3
usunięto katalog/plik3

Kod: Zaznacz cały

< katalog/plik5
usunieto katalog/plik5
Reszta rzeczy z wyjścia diffa Cię nie obchodzi. Jak widzisz interesują cię znaki "<" i ">", wyjście można obrobić przy pomocy awk.
Oczywiście istnieją pewnie lepsze narzędzia do robienia kopi zapasowej :)
RRH
Beginner
Posty: 140
Rejestracja: 27 października 2006, 21:09

Post autor: RRH »

salmon dzięki za zainteresowanie!

Twój opis jest dobry, ale myślę, że do porównywania lepszy będzie wynik:

Kod: Zaznacz cały

     plik01
plik02
plik03
katalog/plik01
katalog/plik02
     katalog/plik03
gdzie od razu widać, że w drugim katalogu brakuje plik01 i katalog/plik03.
Tylko, jak pisałem w poście wyżej, nie wiem jak to porównać.
Najbardziej jednak interesuje mnie takie wyjście z opisem, ale również nie wiem jak to zrobić. :(

Chciałbym się również dowiedzieć, dlaczego działa

Kod: Zaznacz cały

diff --change-group-format=' %<' katalog1Zaw katalog2Zaw 
a nie działa to:

Kod: Zaznacz cały

diff --changed-group-format='%> ' pendZaw dyskZaw
pozdrawiam
salmon
Beginner
Posty: 296
Rejestracja: 12 października 2007, 23:28
Lokalizacja: Gliwice/Bielsko-Biała

Post autor: salmon »

RRH pisze:gdzie od razu widać, że w drugim katalogu brakuje plik01 i katalog/plik03.
Może dla człowieka, nie dla skryptu.
RRH pisze: a nie działa to:
Co znaczy "nie działa"?

A tak w ogóle jak ma ten skrypt wyglądać bo nie jestem pewny? Chcesz żeby generował Ci raport o różnicach w katalogach, czy żeby automatycznie synchronizował zawartość kopi zapasowej z katalogiem?
RRH
Beginner
Posty: 140
Rejestracja: 27 października 2006, 21:09

Post autor: RRH »

Po pierwsze przepraszam, że tak długo nie pisałem.
Jak ma wyglądać skrypt?
Mam sobie kilka katalogów, w tym jeden na ntfs, które potrzebuję często archiwizować.
Kopia zapasowa będzie kopiowana na pendrive.
Skrypt będzie porównywał pliki zapisane na dysku z plikami na pendrivie i kopiował na nośnik wymienny te pliki, których on nie ma (kopia różnicowa).
To właściwie tyle.

Porównanie już częściowo rozwiązałem. A zrobiłem to tak:

skrypt tworzy mi strukturę drzewa dwóch katalogów, dodając na końcu znak separatora:

katalog1

Kod: Zaznacz cały

plik01:
plik02:
plik03:
katalog/plik01:
katalog/plik02:
katalog/plik03:
katalog2

Kod: Zaznacz cały

plik01:
plik03:
katalog/plik01:
katalog/plik02:
Sprawdzam, czy pliki się różnią, dodając przed nazwami plików, których nie ma w katalog2 znak separatora ":",

Kod: Zaznacz cały

diff --changed-group-format=':%<' katalog1 katalog2
różnica

Kod: Zaznacz cały

:p lik01:
plik02:
plik03:
katalog/plik01:
katalog/plik02:
:katalog/plik03:
Teraz analizuję różnicę na podstawie lewej kolumny:

Kod: Zaznacz cały

cut -d: -f1 roznica
co daje:

Kod: Zaznacz cały


plik02
plik03
katalog/plik01
katalog/plik02

Jeżeli linia jest pusta, kopiuję plik, to kopiuję np.plik01 do katalog2.
Jeżeli zaś jest tam nazwa pliku, to sprawdzam, czy na dysku jest nowsza wersja i ewentualnie kopiuję.
Teraz mam problem, bo nie wiem, jak przelatywać pętlą linia po linii (wczytywać ją), ale o to zapytam w innym topicu.

Napisz jeszcze proszę, co sądzisz o takim rozwiązaniu, bo mi wydawało się, że do prostego tworzenia backupów, lepiej napisać skrypt w bashu.

pozdrawiam i dzięki za zainteresowanie
salmon
Beginner
Posty: 296
Rejestracja: 12 października 2007, 23:28
Lokalizacja: Gliwice/Bielsko-Biała

Post autor: salmon »

A może po prostu tak:

Kod: Zaznacz cały

rsync -az --delete  źródło cel
RRH
Beginner
Posty: 140
Rejestracja: 27 października 2006, 21:09

Post autor: RRH »

Przecież rsync służy do wykonywania kopii zapasowych poprzez sieć, no chyba, że się mylę.
Jak znasz jakiś prosty program do robienia kopii zapasowych danych to daj znać. Ja jeszcze poszukam.
Bo chyba lepiej znaleźć jakiś program, niż wymyślać na nowo koło.

Pozdrawiam.
salmon
Beginner
Posty: 296
Rejestracja: 12 października 2007, 23:28
Lokalizacja: Gliwice/Bielsko-Biała

Post autor: salmon »

Przecież Ci napisałem już. źródło i cel to ścieżki do katalogów, pierwszy to katalog, który chcesz wrzucić jako kopię zapasową, a drugi miejscem gdzie chcesz to zapisać.
RRH
Beginner
Posty: 140
Rejestracja: 27 października 2006, 21:09

Post autor: RRH »

Tak, napisałeś - przepraszam za zamieszanie.

Jak dodaje się więcej katalogów źródłowych, to pomocna jest opcja -R:

Kod: Zaznacz cały

rsync -azR --delete  źródło1 źródło2 cel 
Jeszcze pytanie dodatkowe. Czy da się to samo uzyskać samym tarem?
Bo przelotnie przejrzałem mana i dołączania nowszych plików, ale chyba nie ma usuwania starych.
Tak tylko pytam, bo jestem ciekawy.

Pozdrawiam.
salmon
Beginner
Posty: 296
Rejestracja: 12 października 2007, 23:28
Lokalizacja: Gliwice/Bielsko-Biała

Post autor: salmon »

RRH pisze:Czy da się to samo uzyskać samym tarem?
Jedyna odpowiedź jaka mi przychodzi do głowy to: Sprawdź. W podręczniku systemowym niby jest napisane, że jest opcja --delete dla usuwania i -A dla dołączania, ale jak to działa to nie mam pojęcia.
ODPOWIEDZ