rsync kopiuje tylko niektóre typy plików przy użyciu opcji dołączania


110

Używam następującego skryptu bash, aby kopiować tylko pliki o określonym rozszerzeniu (w tym przypadku * .sh), jednak nadal kopiuje wszystkie pliki. Co jest nie tak?

from = 1 $
to = 2 $

rsync -zarv --include = "*. sh" $ od $ do

4
Chociaż nie jest to ściśle powiązane, sugerowałbym cytowanie $ od / $ do. Niezrobienie tego może dać nieoczekiwane rezultaty, jeśli argumenty pozycyjne 1/2 zawierają spacje.
— Kjetil Joergensen

czy zrozumiałeś, dlaczego twoje polecenie nie zadziała?
— Charlie Parker

@CharlieParker: Czy musisz użyć rsync, można to bardzo dobrze osiągnąć za pomocą elementów wewnętrznych powłoki?
— Inian

To, czego brakuje w tym pytaniu i jego odpowiedziom, to jak stworzyć polecenie, jeśli mam katalogi rekurencyjne, do których chcę wysłać tylko jeden typ pliku. Wygląda na to, że robi to tylko dla katalogu docelowego ...
— Charlie Parker

Odpowiedzi:


200

Myślę, że --includejest używany do włączania podzbioru plików, które w przeciwnym razie są wykluczone przez --exclude, a nie tylko do tych plików. Innymi słowy: musisz pomyśleć o uwzględnieniu znaczenia , a nie wykluczaniu .

Spróbuj zamiast tego:

rsync -zarv  --include "*/" --exclude="*" --include="*.sh" "$from" "$to"

W przypadku rsync w wersji 3.0.6 lub nowszej kolejność należy zmodyfikować w następujący sposób (patrz komentarze):

rsync -zarv --include="*/" --include="*.sh" --exclude="*" "$from" "$to"

Dodanie -mflagi pozwoli uniknąć tworzenia pustych struktur katalogów w miejscu docelowym. Przetestowano w wersji 3.1.2.

Więc jeśli chcemy tylko plików * .sh, musimy wykluczyć wszystkie pliki --exclude="*", dołączyć wszystkie katalogi --include="*/"i dołączyć wszystkie pliki * .sh --include="*.sh".

Możesz znaleźć dobre przykłady w sekcji Include / Exclude Pattern Rules na stronie podręcznika


10
Chociaż dostaniesz wszystkie podkatalogi, jeśli są jakieś pliki .sh w podkatalogach, które chcesz rsync, prawdopodobnie będziesz też chciał użyć --include = "* /".
— Kjetil Joergensen

50
Wypróbowałem to na rsync w wersji 3.0.7, którą dostałem dawno temu z macports, i nie działało z taką kolejnością włączeń / wykluczeń. To, co skończyło się, że pracował dla mnie (dostosowany do OP) rsync -zarv --include="*/" --include="*.sh" --exclude="*" "$from" "$to".
— Bijou Trouvaille

3
Próbowałem z rsync 3.0.9 i to nie działa. Bijou ma rację, kolejność nie jest właściwa (pierwszy --include=\*.shwtedy --exclude=\*)
— TrueY

3
Zauważ, że zawsze możesz kliknąć edytuj i zasugerować zmianę w odpowiedzi :)
— Achal Dave,

2
Nie działa w przypadku zamawiania włączeń / wykluczeń, ale działa z kolejnością sugerowaną przez Bijou Trouvaille
— John Smith Opcjonalnie

57

Odpowiedź @chepner skopiuje wszystkie podkatalogi, niezależnie od tego, czy zawiera plik, czy nie. Jeśli chcesz wykluczyć podkatalogi, które nie zawierają pliku i nadal zachowują strukturę katalogów, użyj

rsync -zarv  --prune-empty-dirs --include "*/"  --include="*.sh" --exclude="*" "$from" "$to"

1
To był dla mnie wymóg: „Jeśli chcesz wykluczyć podkatalogi, które nie zawierają pliku i nadal zachowują strukturę katalogów” +1
— Juuso Ohtonen

1
Nie rozumiem, skąd wiedziałeś, jaka była kolejność - zawiera?
— Charlie Parker

1
W jaki sposób można utworzyć polecenie, jeśli mam katalogi rekurencyjne, do których chcę wysłać tylko jeden typ pliku. Wygląda na to, że robi to tylko dla katalogu docelowego.
— Charlie Parker

15

Jeszcze jeden dodatek: jeśli chcesz synchronizować pliki według ich rozszerzeń tylko w jednym katalogu (bez rekursji), powinieneś użyć takiej konstrukcji:

rsync -auzv --include './' --include '*.ext' --exclude '*' /source/dir/ /destination/dir/

Zwróć uwagę na kropkę w pierwszej --include. --no-rnie działa w tej konstrukcji.

EDYTOWAĆ:

Dzięki gbyte.co za cenny komentarz!


1
skąd wiedziałeś, jaka musi być kolejność flag i co powinny zawierać?
— Charlie Parker

1
@CharlieParker, ponieważ wykorzystuje tworzenia serwerów includei excludeopcji w kolejności, w jakiej zostały one określonego w. Poza tym, że zatrzymuje się na pierwszym dopasowane jeden. Tak więc, jeśli określimy --exclude '*'na pierwszym miejscu w tym przykładzie, rsync nic nie zrobi. Zobacz mężczyznę, aby uzyskać więcej wyjaśnień.
— Serge Roussak

czy możesz mi wyjaśnić, co robi każda flaga? Pierwsza flaga -- include './' mówi, że zawierać wszystko w ścieżce katalogu źródłowego? Następnie następny `--include '.ext' 'zawiera określony plik w ścieżce źródłowej o nazwie, .exta następnie wykluczenie mówi, że nie wysyłać niczego więcej --exclude '*'? Czy to jest poprawne?
— Charlie Parker

1
W jaki sposób można utworzyć polecenie, jeśli mam katalogi rekurencyjne, do których chcę wysłać tylko jeden typ pliku. Wygląda na to, że robi to tylko dla katalogu docelowego.
— Charlie Parker

1
Dzięki za to! Musi --include '*.ext'i nie--include '.ext'
— GB

13

Oto ważna część strony podręcznika:

W miarę budowania listy plików / katalogów do przesłania rsync sprawdza po kolei każdą nazwę do przesłania z listą wzorców włączania / wykluczania i wykonywany jest pierwszy pasujący wzorzec: jeśli jest to wzorzec wykluczania, plik ten jest pominięty; jeśli jest to wzorzec włączania, to nazwa pliku nie jest pomijana; jeśli nie zostanie znaleziony pasujący wzorzec, to nazwa pliku nie jest pomijana.

Podsumowując:

  • Brak dopasowania do żadnego wzorca oznacza, że ​​plik zostanie skopiowany!
  • Algorytm kończy działanie po dopasowaniu dowolnego wzorca

Ponadto coś kończącego się ukośnikiem to dopasowywanie katalogów (tak jak find -type dby).

Oddzielmy tę odpowiedź od góry.

rsync -zarv  --prune-empty-dirs --include "*/"  --include="*.sh" --exclude="*" "$from" "$to"
  1. Nie pomijaj żadnych katalogów
  2. Nie pomijaj żadnych .shplików
  3. Pomiń wszystko
  4. (Niejawnie nie pomijaj niczego, ale powyższa reguła zapobiega wystąpieniu reguły domyślnej).

Wreszcie, --prune-empty-directoriespierwsza reguła zapobiega tworzeniu pustych katalogów w każdym miejscu.


Dziękuję bardzo za wyjaśnienie, co się dzieje. Teraz jest znacznie większa szansa, że ​​nie zapomnę polecenia.
— MohamedEzz

3
„Algorytm kończy pracę, gdy którykolwiek wzorzec pasuje” - to jest kluczowe i żadna z wyżej ocenianych odpowiedzi nie wyjaśnia tego tak jasno i z góry, jak tutaj. Oczywiście jest to gdzieś na stronie podręcznika, a jeśli ja przeczytałbym wszystko uważnie, widziałem to. Mimo to, dzięki.
— TheDudeAbides

0

Jeśli ktoś szuka tego… chciałem zsynchronizować tylko określone pliki i foldery i udało mi się to zrobić tym poleceniem: rsync --include-from=rsync-files

Z plikami rsync:

my-dir/
my-file.txt

- /*

0

Napisałem tę przydatną funkcję i umieściłem w moich skryptach bash lub ~/.bash_aliases. Przetestowano synchronizację lokalną w systemie Linux z awkzainstalowanym bashem . To działa

selrsync(){
# selective rsync to sync only certain filetypes;
# based on: https://stackoverflow.com/a/11111793/588867
# Example: selrsync 'tsv,csv' ./source ./target --dry-run
types="$1"; shift; #accepts comma separated list of types. Must be the first argument.
includes=$(echo $types| awk  -F',' \
    'BEGIN{OFS=" ";}
    {
    for (i = 1; i <= NF; i++ ) { if (length($i) > 0) $i="--include=*."$i; } print
    }')
restargs="$@"

echo Command: rsync -avz --prune-empty-dirs --include="*/" $includes --exclude="*" "$restargs"
eval rsync -avz --prune-empty-dirs --include="*/" "$includes" --exclude="*" $restargs
}

Zalety:

krótki, poręczny i rozszerzalny, gdy chce się dodać więcej argumentów (np --dry-run .).

Przykład:

selrsync 'tsv,csv' ./source ./target --dry-run
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.