Ecco la parte importante della pagina man:
Man mano che viene creato l'elenco di file/directory da trasferire, rsync verifica a turno ogni nome da trasferire rispetto all'elenco di pattern di inclusione/esclusione e agisce sul primo pattern corrispondente:se si tratta di un pattern di esclusione, allora quel file viene saltato; se si tratta di un modello di inclusione, il nome del file non viene saltato; se non viene trovato alcun modello corrispondente, il nome del file non viene saltato.
Per riassumere:
- La mancata corrispondenza di alcun modello significa che un file verrà copiato!
- L'algoritmo si chiude quando un pattern corrisponde
Inoltre, qualcosa che termina con una barra corrisponde alle directory (come find -type d
sarebbe).
Analizziamo questa risposta dall'alto.
rsync -zarv --prune-empty-dirs --include "*/" --include="*.sh" --exclude="*" "$from" "$to"
- Non saltare nessuna directory
- Non saltare nessun
.sh
file - Salta tutto
- (Implicitamente, non saltare nulla, ma la regola sopra impedisce che la regola predefinita si verifichi mai.)
Infine, il --prune-empty-directories
impedisce alla prima regola di creare directory vuote ovunque.
Penso --include
è usato per includere un sottoinsieme di file altrimenti esclusi da --exclude
, piuttosto che includere solo quei file. In altre parole:devi pensare a include che significa non escludere .
Prova invece:
rsync -zarv --include "*/" --exclude="*" --include="*.sh" "$from" "$to"
Per rsync versione 3.0.6 o successiva, l'ordine deve essere modificato come segue (vedi commenti):
rsync -zarv --include="*/" --include="*.sh" --exclude="*" "$from" "$to"
Aggiunta del -m
flag eviterà di creare strutture di directory vuote nella destinazione. Testato nella versione 3.1.2.
Quindi se vogliamo solo file *.sh dobbiamo escludere tutti i file --exclude="*"
, includi tutte le directory --include="*/"
e includi tutti i file *.sh --include="*.sh"
.
Puoi trovare alcuni buoni esempi nella sezione Include/Exclude Pattern Rules della pagina man
Un'altra aggiunta:se hai bisogno di sincronizzare i file in base alle sue estensioni in una sola directory (senza ricorsione) dovresti usare una costruzione come questa:
rsync -auzv --include './' --include '*.ext' --exclude '*' /source/dir/ /destination/dir/
Presta attenzione al punto nel primo --include
. --no-r
non funziona in questa costruzione.
MODIFICA:
Grazie a gbyte.co per il prezioso commento!
MODIFICA:
Il -uzv
i flag non sono direttamente correlati a questa domanda, ma li ho inclusi perché li uso di solito.
La risposta di @chepner copierà tutte le sottodirectory indipendentemente dal fatto che contenga file o meno. Se devi escludere le sottodirectory che non contengono il file e mantenere comunque la struttura della directory, usa
rsync -zarv --prune-empty-dirs --include "*/" --include="*.sh" --exclude="*" "$from" "$to"