porównaj 2 katalogi i skopiuj różnice w trzecim katalogu

32

Korzystając z systemu Ubuntu 12.04, chcę porównać 2 katalogi, powiedzmy folder1 / i folder2 / i skopiować wszystkie pliki inne niż folder3 /. Istnieją również pliki zagnieżdżone, więc należy również skopiować pasujące podkatalogi

Czy jest jedno polecenie, które by mi pomogło? Mogę uzyskać pełną listę zmienionych plików:

rsync -rcnC --out-format="%f" folder1/ folder2/

Ale rsync nie wydaje się mieć możliwości „eksportowania” tych plików do innego katalogu docelowego. Czy mogę potokować listę do cp lub innego programu, aby pliki były kopiowane, a katalogi również tworzone? Na przykład próbowałem

rsync -rcnC --out-format="%f" folder1/ folder2/ | xargs cp -t folder3/

ale nie zachowałoby to również katalogów, po prostu skopiowałoby wszystkie pliki w folderze3 /

periklis
źródło
Prawdopodobnie diff -qrawkrsync
użyłbym
jak miałbym używać rsync z listą?
periklis
Uruchomiłbym pętlę for lub skorzystałem z tej rsync --include-from=FILEopcji.
ewwhite
(nie bądź leniwy ...) Ale poniższe rozwiązanie rsync jest eleganckie.
ewwhite

Odpowiedzi:

38

Użyj --compare-dest.

Ze strony podręcznika:

--compare-dest = DIR - Ta opcja instruuje rsync, aby używał DIR na maszynie docelowej jako dodatkowej hierarchii do porównywania plików docelowych z przesyłaniem (jeśli plików brakuje w katalogu docelowym). Jeśli w katalogu DIR zostanie znaleziony plik identyczny z plikiem nadawcy, plik NIE zostanie przesłany do katalogu docelowego. Jest to przydatne do tworzenia rzadkiej kopii zapasowej tylko plików, które zmieniły się od wcześniejszej kopii zapasowej.

najpierw sprawdź swoją składnię za pomocą --dry-run

rsync -aHxv --progress --dry-run --compare-dest=folder2/ folder1/ folder3/

Następnie, gdy jesteś zadowolony z wyników:

rsync -aHxv --progress  --compare-dest=folder2/ folder1/ folder3/

ten link ma dobre wyjaśnienie zakresu --compare-dest.

smithian
źródło
1
Dzięki za to, nie zrozumiałem wyjaśnienia tego parametru na stronie podręcznika. Dla wszystkich zainteresowanych zrobiłem torsync -rcC --compare-dest=folder2/ folder1/ folder3/
periklis
szybka notatka dla użytkowników OsX. Mam rsync version 3.1.1 protocol version 31na swoim lokalnym i rsync nie rozumie ~/ścieżek dla --compare-destparam.
Jevgeni Smirnov
4
Dla mnie --compare-destwymagała absolutnej ścieżki.
palswim
Nie działało dla mnie z opcjami autora ani OP. Oznacza to, że wypisuje fonts/Makefile.inplik, który jest identyczny w obu katalogach folder2i folder1katalogach.
Cześć Anioł,
3

Ten mały skrypt powinien działać:

folder1="firsts_folder/"
folder2="second_folder/"
folder3="target_folder"
for x in `rsync -rcnC --out-format="%n"  $folder1 $folder2`
    do
        if [ -d "$folder1/$x" ]; then
            mkdir -p "$folder3/$x"
        else
            cp -frv $folder1/$x $folder3/$x
        fi
done

Sądzę jednak, że lepszym rozwiązaniem byłoby parsowanie danych wyjściowych diff -qr, ponieważ konsekwentnie podaje ścieżkę i nazwę każdego pliku.

EDYTOWAĆ

To byłoby jedno polecenie, twoje polecenie zostało nieco zmodyfikowane. Ale stworzy folder1pod folder3. I nie działa z pełnymi ścieżkami, ale także powyższy skrypt nie działa z pełnymi ścieżkami.

rsync -rcnC --out-format="\"%f\"" folder1/ folder2/ | xargs cp --parents -rfvt folder3/

Kiedyś \"w rsync, aby pracować z plików i katalogów zawierających spacje. Testowane na Ubuntu 10.04. Mam nadzieję, że to pomoże.

Laurentiu Roescu
źródło
dzięki za to, miałem nadzieję, że będzie jedno polecenie
periklis
2
rsync -rcnC --out-format="%f" . ../folder2/ |xargs cp --parents -rt ../folder3/

Jest to najprostsza forma, jaką mogę wymyślić, jeśli chcesz najpierw zejść folder1 przed wydaniem polecenia.

Jest to wolniejsza opcja, ale uważam, że spełnia twoje wymagania i może być wykonana przy użyciu nierelatywnych nazw katalogów:

rsync -rcnC --out-format="%n" folder1/ folder2/ |grep -vP "/$" |xargs -I{} rsync -R folder1/./{} folder3/

Zostawiłem twój oryginał rsync polecenie w spokoju, ponieważ powiedziałeś, że daje ci poprawną listę plików (a moje pliki testowe są oczywiście inne niż twoje, więc nie mogłem powiedzieć na pewno, że dostanę prawidłową listę plików, jeśli popsuję z tym).

grepJest tam, aby usunąć nazwy katalogów z wyjściarsync .

Dane wyjściowe grepsą następnie przesyłane do innego rsyncza pomocą xargs. W paramie folder1/./{}extra ./jest używane, aby rsync utworzył katalogi względne zaczynające się od ./{}, ignorując folder1/. Innymi słowy, unika tworzeniafolder3/folder1/ .

Mogłem to przetestować tylko na CentOS 6.4, ale AFAIK powinien działać tak samo w Ubuntu 12.04.

EDYCJA: Powinienem zauważyć, że odpowiedź smithiana jest niewątpliwie lepsza, ale chciałem zrobić próbę wykonania tego rsyncpolecenia przy użyciu waszego oryginalnego polecenia, ponieważ dawało to pożądany efekt.

s.co.tt
źródło