rsync copia solo su alcuni tipi di file usando l'opzione include


110

Uso il seguente script bash per copiare solo file di una certa estensione (in questo caso * .sh), tuttavia copia ancora su tutti i file. Cosa c'è che non va?

da = $ 1
a = $ 2

rsync -zarv --include = "*. sh" $ da $ a

4
Sebbene non sia strettamente correlato, suggerirei di citare $ da / $ a. Non farlo potrebbe dare risultati inaspettati se gli argomenti posizionali 1/2 includono spazi.
Kjetil Joergensen

hai capito perché il tuo comando non funzionerebbe?
Charlie Parker

@CharlieParker: devi usare rsync, questo può essere ottenuto molto bene con gli interni della shell?
Inian

Ciò che manca a questa domanda e alle sue risposte è come creare il comando se ho directory ricorsive che voglio inviare solo un tipo di file. Sembra che lo faccia solo per la directory di destinazione ...
Charlie Parker

Risposte:


200

Penso che --includesia usato per includere un sottoinsieme di file che sono altrimenti esclusi da --exclude, piuttosto che includere solo quei file. In altre parole: devi pensare a includere il significato 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"

L'aggiunta del -mflag 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="*", includere tutte le directory --include="*/"e includere tutti i file * .sh --include="*.sh".

Puoi trovare alcuni buoni esempi nella sezione Include / Exclude Pattern Rules della pagina man


10
Anche se ti porterà tutte le sottodirectory, se ci sono file .sh nelle sottodirectory che vuoi rsync, è probabile che vorrai usare anche --include = "* /".
Kjetil Joergensen

50
Ho provato questo su rsync versione 3.0.7, che ho ottenuto molto tempo fa da macports, e non ha funzionato con questo ordine di include / esclude. Questo è quello che ho finito con che ha funzionato per me (adattato per OP): rsync -zarv --include="*/" --include="*.sh" --exclude="*" "$from" "$to".
Bijou Trouvaille

3
Ho provato con rsync 3.0.9 e non ha funzionato. Bijou ha ragione, l'ordinamento non è corretto (prima --include=\*.shquindi --exclude=\*)
TrueY

3
Nota che puoi sempre fare clic su Modifica e suggerire una modifica alla risposta :)
Achal Dave

2
Non funziona con il tuo ordine di include / esclude, ma funziona con l'ordine suggerito da Bijou Trouvaille
John Smith Opzionale

57

La risposta di @chepner copierà tutte le sottodirectory indipendentemente dal fatto che contenga o meno il file. Se è necessario escludere le sottodirectory che non contengono il file e mantengono comunque la struttura della directory, utilizzare

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

1
Questo era un requisito per me: "Se devi escludere le sottodirectory che non contengono il file e mantengono comunque la struttura della directory" +1
Juuso Ohtonen

1
Non capisco come facevi a sapere quale fosse l'ordine degli --inclusi?
Charlie Parker

1
Come si crea il comando se ho directory ricorsive che voglio inviare solo un tipo di file. Sembra che lo faccia solo per la directory di destinazione.
Charlie Parker

15

Un'altra aggiunta: se hai bisogno di sincronizzare i file con le 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-rnon funziona in questa costruzione.

MODIFICARE:

Grazie a gbyte.co per il prezioso commento!


1
come facevi a sapere quale doveva essere l'ordine delle bandiere e cosa dovevano includere?
Charlie Parker

1
@CharlieParker, perché il rsync usa l' includee le excludeopzioni nell'ordine cui sono stati specificati in. In aggiunta a questo, si ferma a quella prima abbinato. Quindi, se specifichiamo --exclude '*'al primo posto in questo esempio, rsync non farà nulla. Vedere l'uomo per ulteriori spiegazioni.
Serge Roussak

puoi spiegarmi cosa sta facendo ogni bandiera? Il primo flag -- include './' sta dicendo includi tutto nel percorso della directory di origine? Quindi il prossimo `--include '.ext'` include il file specifico nel percorso di origine denominato .exte quindi l'esclusione dice non inviare nient'altro --exclude '*'? È corretto?
Charlie Parker

1
Come si crea il comando se ho directory ricorsive che voglio inviare solo un tipo di file. Sembra che lo faccia solo per la directory di destinazione.
Charlie Parker

1
Grazie per questo! Necessario --include '*.ext'e non--include '.ext'
gbyte

13

Ecco la parte importante della pagina man:

Quando viene creato l'elenco di file / directory da trasferire, rsync controlla a turno ogni nome da trasferire rispetto all'elenco di modelli di inclusione / esclusione e si agisce sul primo modello di corrispondenza: se è un modello di esclusione, allora quel file è saltato; se è un pattern di inclusione, il nome del file non viene ignorato; se non viene trovato alcun modello corrispondente, il nome del file non viene ignorato.

Riassumere:

  • Non corrispondere a nessun modello significa che un file verrà copiato!
  • L'algoritmo si chiude una volta che qualsiasi pattern corrisponde

Inoltre, qualcosa che termina con una barra corrisponde alle directory (come find -type dfarebbe).

Separiamo questa risposta dall'alto.

rsync -zarv  --prune-empty-dirs --include "*/"  --include="*.sh" --exclude="*" "$from" "$to"
  1. Non saltare nessuna directory
  2. Non saltare nessun .shfile
  3. Salta tutto
  4. (Implicitamente, non saltare nulla, ma la regola sopra impedisce che la regola predefinita si verifichi.)

Infine, --prune-empty-directoriesmantiene la prima regola di creare directory vuote ovunque.


Grazie mille per aver spiegato cosa sta succedendo. Ora ci sono molte più possibilità che non dimentichi il comando.
MohamedEzz

3
"L'algoritmo si chiude una volta che qualsiasi pattern corrisponde" : questa è la chiave, e nessuna delle risposte più apprezzate lo spiega chiaramente e in modo così chiaro come hai fatto qui. Ovviamente questo è nella pagina man da qualche parte, e se io leggerei tutto attentamente, l'avrei visto. Comunque, grazie.
TheDudeAbides

0

Se qualcuno cerca questo ... volevo rsync solo file e cartelle specifici e sono riuscito a farlo con questo comando: rsync --include-from=rsync-files

Con i file rsync:

my-dir/
my-file.txt

- /*

0

Ho scritto questa pratica funzione e ho inserito i miei script bash o ~/.bash_aliases. Sincronizzazione testata localmente su Linux con bash e awkinstallata. Funziona

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
}

Avantages:

breve pratico ed estensibile quando si desidera aggiungere più argomenti (cioè --dry-run).

Esempio:

selrsync 'tsv,csv' ./source ./target --dry-run
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.