Rsync filtresi: sadece bir modelin kopyalanması


128

Sadece LaTeX'ten derlenmiş tüm PDF'leri barındıracak bir dizin oluşturmaya çalışıyorum. Her projeyi ayrı bir klasörde tutmayı seviyorum, hepsi büyük bir klasörde barındırılıyor LaTeX. Bu yüzden kaçmayı denedim:

rsync -avn *.pdf ~/LaTeX/ ~/Output/

tüm pdfs'leri bulmalı ~/LaTeX/ve bunları çıktı klasörüne transfer etmelidir. Bu işe yaramıyor. Bana " *.pdf" ile eşleşme bulunamadığını söyledi. Bu filtreyi dışarıda bırakırsam, komut LaTeX altındaki tüm proje klasörlerindeki tüm dosyaları listeler. Bu yüzden * .pdf filtresiyle ilgili bir sorun. ~/Ana dizine giden tam yolla değiştirmeyi denedim , ancak bunun bir etkisi olmadı.

Ben zsh kullanıyorum. Bash ve hatta her alt dizindeki her bir dosyayı listeleyen filtre ile aynı şeyi yapmaya çalıştım ... Burada neler oluyor?

Neden rsync sadece pdf filtremi anlamıyor?


TAMAM. Yani güncelleme: Hayır çalışıyorum

rsync -avn --include="*/" --include="*.pdf" LaTeX/ Output/

Ve bu bana bütün dosya listesini verir. Sanırım her şey ilk kalıba uyuyor ...


doğru gibi görünüyorsun ... Sanırım cevabım (zsh'ın **desenini kullanarak ) işe yaramalı .
Marcel Stimberg

Yanıtlar:


248

TL, DR:

rsync -am --include='*.pdf' --include='*/' --exclude='*' ~/LaTeX/ ~/Output/

Rsync kaynakları hedeflere kopyalar. Kaynak *.pdfolarak iletirseniz, kabuk bunu .pdfgeçerli dizinde bulunan dosya listesine genişletir . Hiçbir özyinelemeli geçiş olmaz, çünkü herhangi bir dizini kaynak olarak geçmediniz.

Bu yüzden çalıştırmanız gerekir rsync -a ~/LaTeX/ ~/Output/, ancak rsync'e .pdfyalnızca dosyaları kopyalamasını bildiren bir filtre ile . Kılavuzu okuduğunuzda Rsync'in filtre kuralları göz korkutucu görünebilir, ancak yalnızca birkaç basit kuralla birçok örnek oluşturabilirsiniz.

  • Kapsama alınan terimler ve dışlamalar:

    • Ada veya konuma göre dosyaları hariç kolaydır: --exclude=*~, --exclude=/some/relative/location(örneğin bu hariç tutar kaynak argüman göreli ~/LaTeX/some/relative/location).
    • Yalnızca birkaç dosya veya konumla eşleşmek istiyorsanız, onları dahil edin, bunlara yol açan her dizini (örneğin ile --include=*/) dahil edin, sonra diğerlerini hariç tutun --exclude='*'. Bunun nedeni ise:
    • Bir dizini hariç tutarsanız, bu altındaki her şeyi hariç tutar. Dışlanan dosyalar hiç dikkate alınmayacak.
    • Bir dizin eklerseniz, bu otomatik olarak içeriğini içermez. Son sürümlerde, --include='directory/***'bunu yapacak.
    • Her dosya için ilk eşleme kuralı uygulanır (ve hiçbir zaman eşleşmeyen herhangi bir şey dahil edilir).
  • desenler:

    • Bir model a içermiyorsa /, sans dizini dosya adına uygulanır.
    • Bir model ile sona ererse /, yalnızca dizinlere uygulanır.
    • Bir model ile başlarsa /, argüman olarak geçirilen dizindeki tüm yola uygulanır rsync.
    • *tek bir dizin bileşeninin herhangi bir alt dizini (yani hiçbir zaman eşleşmez /); **herhangi bir yol alt dizgisiyle eşleşir.
  • Bir kaynak bağımsız değişkeni bir ile sona ererse /, içeriği kopyalanır ( rsync -r a/ byaratır b/fooher için a/foo). Aksi takdirde dizinin kendisi kopyalanır ( rsync -r a byaratır b/a).


Bu yüzden burada *.pdf, bunları içeren dizinleri dahil etmemiz ve her şeyi hariç tutmamız gerekir .

rsync -a --include='*.pdf' --include='*/' --exclude='*' ~/LaTeX/ ~/Output/

Bunun, tüm dizinleri, bunlarla eşleşen dosya veya alt dizin içermeyenleri bile kopyaladığını unutmayın. Bu seçenekle bu durumdan kaçınılabilir --prune-empty-dirs(evrensel bir çözüm değildir, çünkü o zaman açıkça eşleştirerek bile bir dizini kopyalayamazsınız, ancak bu nadir bir gerekliliktir).

rsync -am --include='*.pdf' --include='*/' --exclude='*' ~/LaTeX/ ~/Output/

Çözümümün aksine (zsh'ın **şablonunu kullanarak ), bu, dizin dizin yapısını hedef dizinde yeniden oluşturur. OP'nin istediğinin bu olup olmadığından emin değilim ...
Marcel Stimberg

Yalnızca bir dizin eklemek ve /etc/lsyncd/lsyncd.conf.luadosyadaki tüm dizinin geri kalanını hariç tutmak istiyorum . Bir fikrin var mı?
Dhaduk Mitesh

@DhadukMitesh İsyncd ile aşina değilim. Bunu yeni bir soru olarak sormalısınız.
Gilles

25
rsync -av --include="*/" --include="*.pdf" --exclude="*" ~/Latex/ ~/Output/ --dry-run

Varsayılan, her şeyi dahil etmektir , bu nedenle aktarmak istediğiniz dosyaları ekledikten sonra her şeyi açıkça dışlamanız gerekir . Dosyaları gerçekten aktarmak için --dry-run dosyasını kaldırın.

İle başlarsanız:

--exclude '*' --include '*.pdf'

Sonra açgözlü eşleştirme hemen her şeyi hariç tutacak.

Eğer denersen:

--include '*.pdf' --exclude '*' 

Daha sonra sadece üst seviye klasördeki pdf dosyaları aktarılacaktır. '*' Tarafından hariç tutulduğu için hiçbir dizini takip etmeyecektir.


2
2014-03-17 itibariyle, asıl poster sorusunu tam olarak çözdüğü için bu en iyi cevap . Lütfen oy ver! Eklerseniz --prune-empty-dirs(veya kısayol -m), hedefte bir çok boş dizini bile yedeklersiniz, tabii ki onları hatırlatmak veya yapısal bir taslak olarak kullanmak istemezsiniz.
porg

1
En iyi cevap, --include = "* /" anahtardır.
Martin Konicek

Yalnızca bir dizin eklemek ve /etc/lsyncd/lsyncd.conf.luadosyadaki tüm dizinin geri kalanını hariç tutmak istiyorum . Bir fikrin var mı?
Dhaduk Mitesh

15

Eğer böyle bir kalıp kullanırsanız *.pdf, kabuk bu kalıbı “genişletir”, yani kalıbı mevcut dizindeki tüm eşleşmelerle değiştirir. Çalıştırdığınız komut (bu durumda rsync) bir kalıp kullanmaya çalıştığınız gerçeğinin farkında değildir.

Zsh kullanırken , kolay bir çözüm var, ancak: **Desen klasörleri yinelemeli olarak eşleştirmek için kullanılabilir. Bunu dene:

rsync -avn ~/LaTeX/**/*.pdf ~/Output/

Bu, tüm pdfs'leri geçerli dizindeki herhangi bir yerden ve ~ / LaTeX / - ~ / Output arasındaki her şeyi kopyalamaz mı?
SamB

Sanırım demek istedin rsync -avn ~/LaTeX/**/*.pdf ~/Output, ama çözüm --includeyine de daha ölçeklenebilir.
Adam Byrtek

Üzgünüm, aceleyle yazdığım komut düzeltildi ... include komutunun (SamB'nin sürümünde) daha iyi olduğunu kabul ediyorum, ancak **diğer durumlarda da kullanışlı olabilirken , rsync için biraz daha karmaşık ve spesifik olmasına rağmen .
Marcel Stimberg

1
Bash 4 de aynı özelliği benimsemiştir. Oh, ve burada rynync'ye ihtiyacınız yok, cp yapacak. Bazı sistemlerde, çok fazla dosya varsa, cd ~/Latex && cp -p **/*.pdf ~/Output"komut satırı çok uzun" bir hatadan kaçınmak için yardımcı olur .
Gilles

1
Rsync'in filtreleri içerme ve dışlamada kullanılan desenlerinin aynı şeyi yapan bir ** değerine sahip olduğunu unutmayın. Diğer kabuklardan * alıntıları tırnak işaretleri içine alarak kaçabilirsiniz.
Dan Pritts,

13

Sorununuzu çözmek için findve bir ara dosya listesi kullanabilirsiniz files_to_copy. Ana dizininizde bulunduğunuzdan emin olun:

find LaTeX/ -type f -a -iname "*.pdf" > files_to_copy && rsync -avn --files-from=files_to_copy ~/ ~/Output/ && rm files_to_copy

Bash ile test edildi.


Bunun en sağlam çözüm olduğunu düşünüyorum, ancak bul -execseçeneğini kullanmayı veya kullanmayı tercih ederim xargs. Gibi bir şey:find LaTeX/ -type f -iname "*.pdf" -print0 | xargs -0 -i rsync -avn {} Output/
Steven D

Evet ... Ben de bulmak ... Ben rsync hayal olsa öneririm gerekir bunu yapmak mümkün.
gabe.

Bu aynı zamanda daha zor bir soruna da iyi bir çözümdür: Muhtemelen bunu, belge sınıfı olan standaloneveya .texaynı adı taşıyan bir dosyayı içermeyen dosyaları dışlamak için kullanabilirim , çünkü bunlar bazı belgelerde yer alacaklar ...
Seamus

2
rsync seçeneği --files-fromstdin'den okumayı kabul eder. Bu işe find LaTeX/ -type f -a -iname "*.pdf" | rsync -avn --files-from=- ~/ ~/Output/
yarar

9

Arasında "MODEL KURALLARINA EXCLUDE / DAHİL" bölümünde bakılırsa man sayfasına Bunu yapmak için bir yoldur

rsync -avn --include="*/" --include="*.pdf" ~/Latex/ ~/Output/

Bu ve kbrd'ın cevabı arasındaki kritik fark --include="*/", rsync'e ilerlemesini ve isimlerini ne olursa olsun bulduğu tüm dizinleri kopyalamasını söyleyen bayrak. Bu gereklidir, çünkü rsync, bu alt dizini kopyalaması istenmedikçe bir alt dizine tekrar girmeyecektir.

Ayrıca, tırnak işaretlerinin kabuğun, modelleri geçerli dizine göre dosya adlarına genişletmeye çalışmasını ve aşağıdakilerden birini yapmasını engellediğini unutmayın:

  1. Filtrenizi başarmak ve karıştırmak (böyle bir bayrağın ortasında olması pek muhtemel değildir, ancak birisinin ne zaman bir dosya oluşturacağını gerçekten bilemezsiniz --include=foo.pdf...)

  2. Başarısız olmak ve komutu çalıştırmak yerine potansiyel olarak bir hata üretmek (zsh'nin varsayılan olarak yaptığı gibi).


Yani bu sadece PDF'leri ve dizin yapısını kopyalayacak, kbrd dosyaları kopyalayacak, fakat yapıyı görmezden mi gelecek?
Seamus

1
Hmm. Bu aslında hala her şeyi denemek ve kopyalamak gibi görünüyor, sanırım filtre olmadan yaptığı şey bu, çünkü includezaten orada fazladan şeyler yapmak hiçbir şeyi değiştirmiyor. Ne demek istediğimi anlıyorsan ...
Seamus

7
Bundan --exclude="*"sonra ihtiyacınız var --include="*.pdf", yoksa bu her şeyi transfer eder.
jmanning2k

@ jmanning2k: Ah. Bilmek güzel!
SamB

4

Buna ne dersin:

rsync -avn --include="*.pdf" ~/Latex/ ~/Output/

Hayır, man rsyncfiltreyi seçeneklerden sonra ve kaynak / hedeflerden önce koyar. Bunu denedim ve işe yaramadı
Seamus

Sizin yönteminiz mevcut klasörde .pdf dosyalarını bulur, fakat istediğim gibi özyinelemeli değil. ( aseçenek arşiv içindir ve diğer şeylerin yanı sıra kopyalamayı özyinelemelidir
Seamus

1
Hata! Cevabımı güncelledim.
kbyrd

Çok yakın olduğum için +1 ve kılavuzdaki ilgili materyali nasıl bulacağınız konusunda bana ipucu verin. (Umarım bile doğru anladım. :-)
SamB

3

İşte bul kullanmadan çalışması gereken bir şey. Yayınlanan cevaplardan farkı, filtre kurallarının sırasıdır. Bir rsync komutunda filtre kuralları iptable kuralları gibi çalışır, bir dosyanın eşleştiği ilk kural kullanılan kuraldır. Gönderen manuel sayfa :

Aktarılacak dosya / dizin listesi oluşturulduğundan, rsync, sırayla içerme / dışlama kalıpları listesine karşı aktarılacak olan her adı kontrol eder ve ilk eşleme kalıbı hareket eder: eğer bir dışlama kalıbıysa, o dosya atlanır; bir içerme kalıbıysa, o zaman dosya adı atlanmaz; eşleşen bir desen bulunmazsa, dosya adı atlanmaz.

Bu nedenle, aşağıdaki gibi bir komuta ihtiyacınız var:

rsync -avn --include="**.pdf" --exclude="*" ~/LaTeX/ ~/Output/

"**. Pdf" desenine dikkat edin. Göre adam sayfası :

eğer desen bir / (izleyen / değil) veya bir "**" içeriyorsa, önde gelen dizinler de dahil olmak üzere tam yol adına göre eşleştirilir. Desen bir / veya "**" içermiyorsa, yalnızca dosya adının son bileşeniyle eşleştirilir. (Algoritmanın yinelemeli olarak uygulandığını unutmayın; böylece "tam dosya adı", başlangıç ​​dizininden aşağı doğru bir yolun herhangi bir kısmı olabilir.

Küçük testimde, dizin ağacında özyinelemeli çalışır ve sadece pdfs'yi seçer.


Tam olarak nasıl test ettin? Belgeleri anladığıma ve deneysel doğrulamama göre, *.pdfemriniz yalnızca üst düzey dizine kopyalanmalı (değil ~/LaTeX/foo/bar.pdf).
Gilles,

@Gilles Crud. Haklısın. Bunu test ettiğime ve işe yaradığına yemin ettim ama yeniden yaratamam gibi gözüküyor. Ve şimdi alıntı yaptığım man sayfasını okuduğumda, işe yaramadığı anlaşılıyor. Homurdanma.
Steven D

1
Testimin nerede yanlış olduğunu anladım. Benim "küçük test" benim .tex ve .pdf dosyalarının bulunduğu bir dizindeydi. Sonra bir "test" alt dizini ve bu alt dizinde bir test.pdf ve test.tex oluşturdum. Bununla birlikte, muhtemelen üst düzey direktörümde yaptığım bir LaTeX deneyinden dolayı test.pdf olduğunu fark etmedim.
Steven D

Hala anlamadım **. Bunun bir örneği olması iyi olurdu. ;)
buhtz

2

Bu benim tercih ettiğim çözüm:

find source_dir -iname '*.jpg' -print0 |  rsync -0 -v --files-from=- . destination_dir/

Bu findkomutun anlaşılması rsync:-) kuralının dahil etme / dışlama kurallarından daha kolaydır.

Yalnızca pdf dosyalarını kopyalamak istiyorsanız, sadece değiştirmek .jpgiçin.pdf

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.