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
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 .
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
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
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:
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).
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
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 .).
rsync
, można to bardzo dobrze osiągnąć za pomocą elementów wewnętrznych powłoki?Odpowiedzi:
Myślę, że
--include
jest 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:
W przypadku rsync w wersji 3.0.6 lub nowszej kolejność należy zmodyfikować w następujący sposób (patrz komentarze):
Dodanie
-m
flagi 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
źródło
rsync -zarv --include="*/" --include="*.sh" --exclude="*" "$from" "$to"
.--include=\*.sh
wtedy--exclude=\*
)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
źródło
Jeszcze jeden dodatek: jeśli chcesz synchronizować pliki według ich rozszerzeń tylko w jednym katalogu (bez rekursji), powinieneś użyć takiej konstrukcji:
Zwróć uwagę na kropkę w pierwszej
--include
.--no-r
nie działa w tej konstrukcji.EDYTOWAĆ:
Dzięki gbyte.co za cenny komentarz!
źródło
include
iexclude
opcji 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ń.-- 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,.ext
a następnie wykluczenie mówi, że nie wysyłać niczego więcej--exclude '*'
? Czy to jest poprawne?--include '*.ext'
i nie--include '.ext'
Oto ważna część strony podręcznika:
Podsumowując:
Ponadto coś kończącego się ukośnikiem to dopasowywanie katalogów (tak jak
find -type d
by).Oddzielmy tę odpowiedź od góry.
.sh
plikówWreszcie,
--prune-empty-directories
pierwsza reguła zapobiega tworzeniu pustych katalogów w każdym miejscu.źródło
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:
źródło
Napisałem tę przydatną funkcję i umieściłem w moich skryptach bash lub
~/.bash_aliases
. Przetestowano synchronizację lokalną w systemie Linux zawk
zainstalowanym bashem . To działaZalety:
krótki, poręczny i rozszerzalny, gdy chce się dodać więcej argumentów (np
--dry-run
.).Przykład:
źródło