Jak zsynchronizować tylko określoną listę plików?

95

Mam około 50 plików w różnych podkatalogach, które chciałbym przesłać na zdalny serwer. Pomyślałem, że rsync będzie w stanie to dla mnie zrobić, używając opcji --include-from. Bez opcji --exclude = "*" wszystkie pliki w katalogu są synchronizowane, z opcją żadne pliki nie są synchronizowane.

rsync -avP -e ssh --include-from=deploy/rsync_include.txt --exclude=* ./ [email protected]:/var/www/ --dry-run

Uruchamiam go jako suchy początkowo i 0.0.0.0 jest oczywiście zastępowane przez adres IP zdalnego serwera. Zawartość rsync_include.txt to lista oddzielonych wierszami ścieżek względnych do plików, które chcę przesłać.

Czy jest lepszy sposób na to, że ucieknie mi w poniedziałek rano?

Dan Steele
źródło

Odpowiedzi:

4

Edycja: odpowiedź Josipa Rodina poniżej jest lepsza. Proszę, użyj tego!

Możesz mieć łatwiejszy czas, jeśli szukasz określonej listy plików, umieszczając je bezpośrednio w wierszu poleceń:

# rsync -avP -e ssh `cat deploy/rsync_include.txt` [email protected]:/var/www/

Zakłada się jednak, że twoja lista nie jest tak długa, że ​​długość wiersza poleceń będzie problemem i że rsync_include.txtplik zawiera tylko rzeczywiste ścieżki (tj. Bez komentarzy i wyrażeń regularnych).

Wes Hardaker
źródło
9
Niestety to nie działa w przypadku dużej listy lub plików ze spacjami w nazwie.
Wes Modes
3
[Lista argumentów jest zbyt długa]
Dankó Dávid
Domyślnie xargs dołącza argumenty ze standardowego wejścia na koniec wiersza poleceń. To nie działa, ponieważ rsync potrzebuje ostatniego argumentu jako miejsca docelowego. Niektóre wersje xargs mogą zamiast tego wstawiać argumenty w środku linii poleceń. To powinno działać, o ile nie masz nic przeciwko temu, że może uruchomić rsync więcej niż jeden raz, gdy lista plików jest długa. W każdym razie rsync --files-fromjest to prawdopodobnie łatwiejsze i bardziej niezawodne rozwiązanie :)
Lassi
Wes Hardaker: Czy Twój Edit odniesienie i do „odpowiedzi Josipa Rodina” faktycznie odnoszą się do @atp odpowiedź , że Rodin edytowane?
Seamus
234

Jest flaga, --files-fromktóra robi dokładnie to, co chcesz. Od man rsync:

--files-from=FILE

Użycie tej opcji umożliwia określenie dokładnej listy plików do przesłania (odczytanej z określonego PLIKU lub - w przypadku standardowego wejścia). Poprawia również domyślne zachowanie rsync, aby ułatwić przesyłanie tylko określonych plików i katalogów:

  • Implikowana jest opcja --relative (-R), która zachowuje informacje o ścieżce, które są określone dla każdego elementu w pliku (użyj --no -relative lub --no-R, jeśli chcesz to wyłączyć).

  • Implikowana jest opcja --dirs (-d), która utworzy katalogi określone na liście w miejscu docelowym, zamiast hałaśliwie je pomijać (użyj --no-dirs lub --no-d, jeśli chcesz to wyłączyć).

  • Zachowanie opcji --archive (-a) nie implikuje --recursive (-r), więc określ to jawnie, jeśli chcesz.

  • Te efekty uboczne zmieniają domyślny stan rsync, więc pozycja opcji --files-from w wierszu poleceń nie ma wpływu na sposób analizowania innych opcji (np. -A działa tak samo przed i po --files- from, podobnie jak --no-R i wszystkie inne opcje).

Nazwy plików, które są odczytywane z PLIKU, są wszystkie względne w stosunku do katalogu źródłowego - wszelkie początkowe ukośniki są usuwane i żadne odniesienia „..” nie mogą być wyższe niż katalog źródłowy. Na przykład weź to polecenie:

rsync -a --files-from=/tmp/foo /usr remote:/backup

Jeśli / tmp / foo zawiera ciąg „bin” (lub nawet „/ bin”), katalog / usr / bin zostanie utworzony jako / backup / bin na zdalnym hoście. Jeśli zawiera „bin /” (zwróć uwagę na końcowy ukośnik), zostanie również wysłana bezpośrednia zawartość katalogu (bez konieczności wyraźnego wzmianki o tym w pliku - zaczęło się to w wersji 2.6.4). W obu przypadkach, jeśli opcja -r byłaby włączona, cała hierarchia tego katalogu również zostałaby przeniesiona (należy pamiętać, że -r musi być podane jawnie z --files-from, ponieważ nie jest implikowane przez -a). Zwróć również uwagę, że efektem opcji (domyślnie włączona) --relative jest powielenie tylko informacji o ścieżce, które są odczytywane z pliku - nie wymusza to duplikacji ścieżki źródłowej (w tym przypadku / usr) .

Ponadto plik --files-from można odczytać z hosta zdalnego zamiast z hosta lokalnego, jeśli określisz „host:” przed plikiem (host musi pasować do jednego końca transferu). Jako skrót możesz podać przedrostek „:” oznaczający „użyj zdalnego końca transferu”. Na przykład:

rsync -a --files-from=:/path/file-list src:/ /tmp/copy

Spowoduje to skopiowanie wszystkich plików określonych w pliku / path / file-list, który znajdował się na zdalnym hoście „src”.

Jeśli podano opcje --iconv i --protect-args, a nazwy plików --files-from są wysyłane z jednego hosta do drugiego, nazwy plików zostaną przetłumaczone z zestawu znaków hosta wysyłającego na zestaw znaków hosta odbierającego.

UWAGA: sortowanie listy plików w wejściu --files-from pomaga rsync być bardziej wydajnym, ponieważ pozwoli uniknąć ponownego odwiedzania elementów ścieżki, które są współdzielone między sąsiednimi wpisami. Jeśli dane wejściowe nie są posortowane, niektóre elementy ścieżek (domniemane katalogi) mogą zostać przeskanowane wiele razy, a rsync ostatecznie cofnie ich duplikację po przekształceniu ich w elementy listy plików.

atp
źródło
23
Zauważ, że nadal musisz określić katalog, w którym znajdują się wymienione pliki, na przykład: rsync -av --files-from=file-list . target/do kopiowania plików z bieżącego katalogu.
Nicolas Mattia,
7
Tak, i powtórzyć: The filenames that are read from the FILE are all relative to the source dir.
ATP
Ach, przegapiłem to, przepraszam!
Nicolas Mattia,
1
jeśli plik-z pliku ma coś zaczynającego się od ..rsync, wydaje się, że ignoruje ..błąd, taki jak rsync: link_stat "/home/michael/test/subdir/test.txt" failed: No such file or directory(w tym przypadku uruchomienie z katalogu "test" i próba określenia "../subdir/test.txt", który istnieje.
Michael
Czy --files-fromargument można połączyć z jawną listą --files-fromwłączeń i wykluczeń i czy pliki z listy dodane z nadpisaniem istniejących reguł wykluczania, tak że zostaną uwzględnione, jeśli pojawią się w pliku?
highsciguy
13

--files-from=parametr wymaga końcowego ukośnika, jeśli chcesz zachować bezwzględną ścieżkę nienaruszoną. Więc twoje polecenie zmieniłoby się w coś takiego jak poniżej:

rsync -av --files-from=/path/to/file / /tmp/

Można to zrobić tak, jakby istniała duża liczba plików i chcesz skopiować wszystkie pliki do ścieżki x. Więc znalazłbyś pliki i wyrzucił dane wyjściowe do pliku takiego jak poniżej:

find /var/* -name *.log > file
Waqas Khan
źródło
9

Dla przypomnienia, żadna z powyższych odpowiedzi nie pomogła poza jedną. Podsumowując, możesz wykonać operację tworzenia kopii zapasowej za --files-from=pomocą:

 rsync -aSvuc `cat rsync-src-files` / mnt / d / rsync_test /

LUB

rsync -aSvuc --recursive --files-from = rsync-src-files. / mnt / d / rsync_test /

To pierwsze polecenie jest oczywiste, poza treścią pliku, rsync-src-filesktóry omówię poniżej. Teraz, jeśli chcesz korzystać z drugiej wersji, musisz pamiętać o następujących czterech uwagach:

  1. Zauważ, że należy określić oba --files-fromi katalog źródłowy
  2. Trzeba to wyraźnie określić --recursive.
  3. Plik rsync-src-filesjest plikiem utworzonym przez użytkownika i został umieszczony w katalogu src na potrzeby tego testu
  4. rsyn-src-filesZawierać pliki i foldery do skopiowania i są podejmowane w stosunku do katalogu źródłowego. WAŻNE: upewnij się, że w pliku nie ma końcowych spacji ani pustych wierszy. W poniższym przykładzie są tylko dwie linie, a nie trzy (zorientuj się przypadkowo). Treść rsynch-src-filesto:

nazwa_folderu1
nazwa_folderu2

KF
źródło
3

Dostałem podobne zadanie: rsync wszystkie pliki zmodyfikowane po podanej dacie, ale z wyłączeniem niektórych katalogów. Trudno było zbudować jeden liniowy styl all-in-one, więc podzieliłem problem na mniejsze części. Ostateczne rozwiązanie:

find  ~/sourceDIR -type f -newermt "DD MMM YYYY HH:MM:SS" | egrep -v "/\..|Downloads|FOO" > FileList.txt
rsync -v --files-from=FileList.txt ~/sourceDIR /Destination

Najpierw używam find -L ~/sourceDIR -type f -newermt "DD MMM YYYY HH:MM:SS". Próbowałem dodać regexdo findwiersza, aby wykluczyć wzorce nazw, jednak mój smak Linuksa (Mint) wydaje się nie rozumieć negacji wyrażenia regularnego find. Wypróbowana liczba smaków wyrażenia regularnego - nie działa zgodnie z oczekiwaniami. Skończyło się na egrep -vopcji, która wyklucza łatwy sposób tworzenia wzoru. Mój rsyncnie kopiuje katalogów takich jak /.cache czy /.config plus kilka innych, które wyraźnie wymieniłem.

sopel
źródło
1
Uważam, że można użyć substytucji procesu, aby przekształcić to w bashrsync -v --files-from=<(find ~/sourceDIR -type f -newermt "DD MMM YYYY HH:MM:SS" | grep -Ev "/\..|Downloads|FOO") ~/sourceDIR /Destination
jednolinijkowy
2
$ date
  Wed 24 Apr 2019 09:54:53 AM PDT
$ rsync --version
  rsync  version 3.1.3  protocol version 31
  ...

Składnia: rsync <file_/_folder_list> <source> <target>

Nazwy folderów (tutaj z końcem /; np. Cancer - Evolution/) Znajdują się w pliku listy folderów (np .: cm_folder_list_test):

# /mnt/Vancouver/projects/ie/claws/data/cm_folder_list_test
# test file: 2019-04-24
Cancer/
Cancer - Evolution/
Cancer - Genomic Variants/
Cancer - Metastasis (EMT Transition ...)/
Cancer Pathways, Networks/
Catabolism - Autophagy; Phagosomes; Mitophagy/
Catabolism - Lysosomes/

Jeśli nie uwzględnisz tych końcowych /, foldery docelowe rsync zostaną utworzone, ale będą puste.

Te nazwy folderów są dołączane do reszty ich path ( /home/victoria/Mail/2_RESEARCH - NEWS), zapewniając w ten sposób pełną ścieżkę folderu do rsync; np /home/victoria/Mail/2_RESEARCH - NEWS/Cancer - Evolution/. : .

Pamiętaj, że musisz również użyć --files-from=..., NOT --include-from=...

rsync -aqP --delete --files-from=/mnt/Vancouver/projects/ie/claws/data/cm_folder_list_test "/home/victoria/Mail/2_RESEARCH - NEWS" $IN/

(W moim skrypcie BASH zdefiniowałem zmienną $INw następujący sposób.)

BASEDIR="/mnt/Vancouver/projects/ie/claws"
IN=$BASEDIR/data/test/input

użyte opcje rsync:

 -a  :   archive: equals -rlptgoD (no -H,-A,-X)
    -r  :   recursive
    -l  :   copy symlinks as symlinks
    -p  :   preserve permissions
    -t  :   preserve modification times 
    -g  :   preserve group 
    -o  :   preserve owner (super-user only) 
    -D  :   same as --devices --specials 
  -q  :   quiet (/server/547106/run-totally-silent-rsync)

  --delete
    This  tells  rsync to delete extraneous files from the RECEIVING SIDE (ones
    that AREN’T ON THE SENDING SIDE), but only for the directories that are
    being synchronized.  You must have asked rsync to send the whole directory
    (e.g.  "dir" or "dir/") without using a wildcard for the directory’s contents
    (e.g. "dir/*") since the wildcard is expanded by the shell and rsync thus
    gets a request to transfer individual files, not the files’ parent directory.
    Files  that  are  excluded  from  the transfer are also excluded from being
    deleted unless you use the --delete-excluded option or mark the rules as
    only matching on the sending side (see the include/exclude modifiers in the
    FILTER RULES section).  ...
Victoria Stuart
źródło
1

Ta odpowiedź nie jest bezpośrednią odpowiedzią na pytanie. Powinien jednak pomóc Ci ustalić, które rozwiązanie najlepiej pasuje do Twojego problemu.

Analizując problem, należy aktywować opcję debugowania -vv

Następnie rsync wyświetli, które pliki są uwzględnione lub wykluczone według którego wzorca:

building file list ... 
[sender] hiding file FILE1 because of pattern FILE1*
[sender] showing file FILE2 because of pattern *
Matthias M.
źródło
0

Żadna z tych odpowiedzi nie zadziałała dla mnie, kiedy jedyne, co miałem, to lista katalogów . Wtedy natknąłem się na rozwiązanie! Musisz dodać -rdo, --files-fromponieważ -aw tym scenariuszu nie będzie rekurencyjny (kto wie ?!).

rsync -aruRP --files-from=directory.list . ../new/location
Theodore R. Smith
źródło
Jeśli w pliku znajduje się „dir”, musisz określić -r / —recursive; jeśli podasz „dir /”, nie.
lbutlr