2009-05-11 13 views
7

ho un semplice script bash prova che si presenta così:script file di vs della riga di comando: rsync e --exclude

#!/bin/bash 

cmd="rsync -rv --exclude '*~' ./dir ./new" 
$cmd # execute command 

Quando eseguo lo script copierà anche i file che terminano con un ~ anche se intendevo escluderli. Quando eseguo lo stesso comando rsync direttamente dalla riga di comando, funziona! Qualcuno sa perché e come far funzionare lo script di bash?

Btw, so che posso anche lavorare con --exclude-from ma voglio sapere come funziona comunque.

risposta

5

Prova eval:

#!/bin/bash 

cmd="rsync -rv --exclude '*~' ./dir ./new" 
eval $cmd # execute command 
0

È possibile utilizzare un semplice --eclude '~' come (accoding alla pagina man):

  • se il modello comincia con una/allora è ancorato ad un punto particolare nel la gerarchia dei file, altrimenti it viene confrontato con la fine del nome del percorso . È simile a uno principale nelle espressioni regolari. Quindi "/ foo" corrisponderebbe a un nome di "foo" su "root del trasferimento" (per una regola globale ) o nella directory del file di unione (per una regola per directory). Un "pippo" non qualificato corrisponderebbe a un nome di "pippo" in qualsiasi punto dell'albero poiché l'algoritmo viene applicato ricorsivamente dall'alto verso il basso; it si comporta come se ogni componente del percorso ottenga un turno alla fine del nome file . Anche il sottodimensionato "sub/foo" corrisponderebbe in qualsiasi punto di alla gerarchia in cui è stato trovato un "foo" all'interno di una directory denominata "sub". Vedere la sezione su ANCORAGGIO INCLUDE/EXCLUDE PATTERNS per una discussione completa su come specificare un modello che corrisponde alla radice del trasferimento .
  • se il modello termina con a/allora corrisponderà solo a una directory, non a un file regolare , a un collegamento simbolico oa un dispositivo.
  • rsync sceglie tra il fare una semplice partita di stringa e wildcard corrispondenza controllando se il modello contiene uno di questi tre jolly caratteri: '?' '*', E '['.
  • un '*' corrisponde a qualsiasi componente del percorso, ma si arresta alle barre.
  • utilizzare '**' per abbinare qualsiasi cosa, comprese le barre.
4

Il problema non è che si sta eseguendo in uno script, è che si mette il comando in una variabile e quindi eseguire la variabile espansa . E poiché l'espansione delle variabili avviene dopo che la rimozione delle quote è già stata eseguita, le virgolette singole attorno al pattern di esclusione non vengono mai rimosse ... e quindi rsync termina escludendo i file con nomi che iniziano con "e finiscono con ~".Per risolvere questo problema, è sufficiente rimuovere le virgolette intorno al modello (il tutto è già tra virgolette, in modo che non sono necessari):

#!/bin/bash 

cmd="rsync -rv --exclude *~ ./dir ./new" 
$cmd # execute command 

... A proposito, perché stai mettendo il comando in una variabile prima di eseguirlo? In generale, questo è un buon modo per rendere il codice più confusionario di quanto dovrebbe essere, e innescare stranezze parsing (alcune anche più bizzarre di questa). Quindi che dire:

#!/bin/bash 

rsync -rv --exclude '*~' ./dir ./new 
+0

L'ho messo in una variabile per il debug. Ho iniziato senza virgolette singole e questo era ancora peggio (in realtà, è per questo che li ho messi lì) a causa dell'espansione. Per esempio. "rsync -r --exclude * ~ ./dir ./new" espanso a "rsync -r --exclude foo ~ bar ~ foobar.sh ~ ./dir ./new" – Chris

+0

Lo hai provato con le virgolette singole, ma senza metterlo in una variabile (come nella mia seconda raccomandazione)? Dovrebbe funzionare bene (e sembrava quando l'ho provato). –

Problemi correlati