2009-05-11 27 views
7

böyle görünüyor basit bir test bash script var:komut satırı vs komut dosyası: rsync ve --exclude

#!/bin/bash 

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

Ben aynı zamanda bir ~ ile biten dosyaları kopyalar komut dosyası çalıştırdığınızda onları dışlamak istedim bile. Aynı rsync komutunu doğrudan komut satırından çalıştırdığımda çalışır! Birisi bash betiğinin neden ve nasıl yapıldığını biliyor mu?

Btw, ben de --exclude-from çalışabilirsiniz biliyorum ama bu yine de nasıl çalıştığını bilmek istiyorum.

cevap

5

eval deneyin:

#!/bin/bash 

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

Sen (Adam sayfasına doğrultusunda kapsamınızı) gibi basit --eclude '~' kullanabilirsiniz: desen dosyalarının bir/o zaman belirli bir noktaya sabitlenir hiyerarşi ile başlar, aksi takdirde,

  • , yol adının sonuna karşılık gelir. Bu, düzenli ifadelerde önde gelen ^ ile benzerdir. Böylece "/ foo" , "aktarımın kökü" (bir genel kuralı için) ya da birleştirme dosyasının dizinindeki (dizin başına bir kural için) "foo" adıyla eşleşir. Algoritma yukarıdan aşağı yinelemeli uygulandığı çünkü bir niteliksiz "foo" ağacının herhangi bir yerinde "foo" bir adını eşleşir; , her yol bileşeninin, dosya adını dosya adının sonuna gelmesi gibi davranır. "Alt" adlı bir dizinde "alt/foo" bile hiyerarşisinde herhangi bir noktada eşleşecek "fay" bulundu. aktarımının kökü ile eşleşen bir deseninin nasıl belirtileceğine ilişkin ANCHORING INCLUDE/EXCLUDE PATTERNS bölümüne bakın.
  • Desen bir/ile bitiyorsa, yalnızca bir diziyle eşleşecek, bir düzenli dosya, sembolik bağlantı veya aygıtla eşleşmeyecektir. desen bu üç joker karakterlerinden biri içeriyorsa
  • rsync kontrol ederek basit bir dize maç ve wildcard eşleştirme yaparak arasında seçer: '?' '*', ve '['.
  • a '*' herhangi bir yol bileşeniyle eşleşir, ancak eğik çizgide durur.
  • Eğik çizgileri dahil olmak üzere her şeyi eşleştirmek için '**' kullanın.
4

Sorun şu ki sen bir senaryoya çalıştırdığınız değil yani, bir değişkene komutu koymak ve daha sonra genişletilmiş değişkeni çalıştırmak işte . Alıntı kaldırma işlemi zaten yapıldıktan sonra değişken genişleme gerçekleştiği için, dışlama deseninizin etrafındaki tek tırnaklar çıkarılmaz ... ve böylece rsync, 'ile başlayan ve' ile biten adlar içeren dosyaları dışarda bırakır.Sadece (Her şey çift tırnak zaten, bu yüzden gerekli değildir) desen etrafında tırnak kaldırın Bunu düzeltmek için:

#!/bin/bash 

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

... açılmışken, neden komutu koyarak arasında çalıştırmadan önce bir değişkende? Genel olarak, bu, kodun olması gerekenden daha karmaşık hale getirmenin iyi bir yoludur ve ayrıştırma tuhaflıklarını tetikler (bazıları bundan daha da gariptir). Peki, nasıl olur:

#!/bin/bash 

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

Hata ayıklamak için bir değişkene koydum. Tek tırnaksız olarak başladım ve bu daha da kötüydü (aslında, bu yüzden onları oraya koydum). Örneğin. "rsync -r --exclude * ~ ./dir ./new" rsync -r --exclude foo ~ bar ~ foobar.sh ~ ./dir ./new "'ye genişletildi." " – Chris

+0

Tek tırnaklar ile denediniz mi? ama bir değişkene koymadan (ikinci tavsiyemde olduğu gibi)? İyi çalışmalı (ve bunu test ettiğimde göründü). –