it-swarm-id.com

Rsync filter: menyalin satu pola saja

Saya mencoba membuat direktori yang akan menampung semua dan hanya PDF saya yang dikompilasi dari LaTeX. Saya suka menyimpan setiap proyek di folder terpisah, semua disimpan di folder besar bernama LaTeX. Jadi saya mencoba berlari:

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

yang seharusnya menemukan semua pdf di ~/LaTeX/ dan transfer ke folder output. Ini tidak berhasil. Ini memberitahu saya bahwa tidak ada kecocokan untuk "*.pdf ". Jika saya meninggalkan filter ini, perintah ini mencantumkan semua file di semua folder proyek di bawah LaTeX. Jadi ini masalah dengan filter * .pdf. Saya mencoba mengganti ~/ dengan path lengkap ke direktori home saya, tetapi itu tidak berpengaruh.

Saya menggunakan zsh. Saya mencoba melakukan hal yang sama di bash dan bahkan with filter yang mendaftar setiap file di setiap subdirektori ... Apa yang terjadi di sini?

Mengapa rsync tidak memahami hanya filter pdf saya?


BAIK. Jadi perbarui: Tidak, saya sedang mencoba

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

Dan ini memberi saya seluruh daftar file. Saya kira karena semuanya cocok dengan pola pertama ...

142
Seamus

TL, DR:

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

Rsync menyalin sumber ke tujuan. Jika Anda lulus *.pdf sebagai sumber, Shell memperluas ini ke daftar file dengan .pdf ekstensi dalam direktori saat ini. Tidak ada traversal rekursif yang terjadi karena Anda tidak melewatkan direktori apa pun sebagai sumber.

Jadi Anda perlu menjalankan rsync -a ~/LaTeX/ ~/Output/, tetapi dengan filter untuk memberitahu rsync untuk menyalin .pdf file saja. Aturan filter Rsync tampak menakutkan ketika Anda membaca manual, tetapi Anda dapat membuat banyak contoh hanya dengan beberapa aturan sederhana.

  • Inklusi dan pengecualian:

    • Mengecualikan file berdasarkan nama atau lokasi mudah: --exclude=*~, --exclude=/some/relative/location (relatif terhadap argumen sumber, mis. ini tidak termasuk ~/LaTeX/some/relative/location).
    • Jika Anda hanya ingin mencocokkan beberapa file atau lokasi, sertakan mereka, sertakan setiap direktori yang mengarah ke mereka (misalnya dengan --include=*/), lalu kecualikan sisanya dengan --exclude='*'. Hal ini karena:
    • Jika Anda mengecualikan direktori, ini mengecualikan semua yang ada di bawahnya. File yang dikecualikan tidak akan dianggap sama sekali.
    • Jika Anda memasukkan direktori, ini tidak termasuk isinya secara otomatis. Dalam versi terbaru, --include='directory/***' akan melakukan itu.
    • Untuk setiap file, aturan pencocokan pertama berlaku (dan apa pun yang tidak pernah cocok disertakan).
  • Pola:

    • Jika suatu pola tidak mengandung /, ini berlaku untuk direktori nama file sans.
    • Jika suatu pola diakhiri dengan /, ini hanya berlaku untuk direktori.
    • Jika suatu pola dimulai dengan /, ini berlaku untuk keseluruhan path dari direktori yang diteruskan sebagai argumen ke rsync.
    • * substring dari komponen direktori tunggal (mis. tidak pernah cocok /); ** cocok dengan substring jalur apa pun.
  • Jika argumen sumber berakhir dengan /, isinya disalin (rsync -r a/ b membuat b/foo untuk setiap a/foo). Kalau tidak, direktori itu sendiri akan disalin (rsync -r a b membuat b/a).


Jadi di sini kita perlu memasukkan *.pdf, sertakan direktori yang memuatnya, dan kecualikan yang lainnya.

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

Perhatikan bahwa ini menyalin semua direktori, bahkan yang tidak mengandung file yang cocok atau subdirektori yang mengandungnya. Ini bisa dihindari dengan --Prune-empty-dirs pilihan (itu bukan solusi universal karena Anda kemudian tidak dapat menyalin direktori bahkan dengan mencocokkannya secara eksplisit, tapi itu persyaratan yang langka).

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

Defaultnya adalah untuk memasukkan semuanya, jadi Anda harus secara eksplisit mengecualikan semuanya setelah termasuk file yang ingin Anda transfer. Hapus --dry-run untuk benar-benar mentransfer file.

Jika Anda memulai dengan:

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

Kemudian pencocokan serakah akan mengecualikan semuanya langsung.

Jika kamu mencoba:

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

Maka hanya file pdf di folder tingkat atas yang akan ditransfer. Itu tidak akan mengikuti direktori apa pun, karena itu dikecualikan oleh '*'.

30
jmanning2k

Jika Anda menggunakan pola seperti *.pdf, Shell “memperluas” pola itu, yaitu mengganti pola dengan semua kecocokan di direktori saat ini. Perintah yang Anda jalankan (dalam hal ini rsync) tidak mengetahui fakta bahwa Anda mencoba menggunakan pola.

Ketika Anda menggunakan zsh, ada solusi mudah, meskipun: The ** pola dapat digunakan untuk mencocokkan folder secara rekursif. Coba ini:

rsync -avn ~/LaTeX/**/*.pdf ~/Output/
15
Marcel Stimberg

Anda dapat menggunakan find dan daftar file antara (files_to_copy) untuk menyelesaikan masalah Anda. Pastikan Anda berada di direktori home Anda, lalu:

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

Diuji dengan Bash.

13
Derek Frye

Dinilai oleh bagian "TERMASUK/MENGECUALIKAN POLA" halaman manual , cara untuk melakukan ini adalah

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

Perbedaan kritis antara ini dan jawaban kbrd adalah --include="*/" flag, yang memberitahu rsync untuk melanjutkan dan menyalin direktori apa pun yang ditemukannya, apa pun namanya. Ini diperlukan karena rsync tidak akan muncul lagi ke dalam subdirektori kecuali telah diperintahkan untuk menyalin subdirektori itu.

Juga, perhatikan bahwa tanda kutip mencegah Shell dari mencoba memperluas pola ke nama file relatif ke direktori saat ini, dan melakukan salah satu dari yang berikut:

  1. Berhasil dan mengacaukan filter Anda (tidak terlalu mungkin di tengah-tengah bendera seperti itu, meskipun Anda benar-benar tidak pernah tahu kapan seseorang akan membuat file bernama --include=foo.pdf ...)

  2. Gagal, dan berpotensi menghasilkan kesalahan alih-alih menjalankan perintah (seperti yang Anda temukan zsh lakukan secara default).

9
SamB

Ini adalah solusi pilihan saya:

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

Perintah find lebih mudah dipahami daripada aturan sertakan/kecualikan dari rsync :-)

Jika Anda hanya ingin menyalin file pdf, ubah saja .jpg hingga .pdf

3
guettli

Bagaimana dengan ini:

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

Berikut adalah sesuatu yang harus berfungsi tanpa menggunakan find. Perbedaan dari jawaban yang sudah diposting adalah urutan aturan filter. Aturan filter dalam perintah rsync bekerja sangat mirip dengan aturan iptable, aturan pertama yang cocok dengan file adalah yang digunakan. Dari halaman manual :

Ketika daftar file/direktori yang akan ditransfer dibangun, rsync memeriksa setiap nama yang akan ditransfer terhadap daftar pola include/exclude secara bergantian, dan pola pencocokan pertama dijalankan: jika itu adalah pola kecualikan, maka file tersebut adalah dilewati; jika itu adalah pola sertakan maka nama file itu tidak dilewati; jika tidak ditemukan pola yang cocok, maka nama file tidak dilewati.

Dengan demikian, Anda memerlukan perintah sebagai berikut:

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

Perhatikan pola "**. Pdf". Menurut halaman manual :

jika polanya berisi a/(tidak termasuk trailing /) atau "**", maka itu dicocokkan dengan pathname lengkap, termasuk direktori utama mana pun. Jika polanya tidak mengandung a/atau "**", maka itu hanya cocok dengan komponen akhir dari nama file. (Ingat bahwa algoritma ini diterapkan secara rekursif sehingga "nama file lengkap" sebenarnya dapat menjadi bagian dari jalur dari direktori awal ke bawah

Dalam pengujian kecil saya, ini bekerja secara rekursif ke bawah pohon direktori dan hanya memilih pdf.

2
Steven D

Untuk menghasilkan direktori yang hanya berisi tajuk (../include) dari dalam direktori sumber:

rsync -avh --Prune-empty-dirs --exclude="build" --include="*/" --include="*.h" --exclude="*" ./* ../include/

Ini mengecualikan semua direktori kosong dan direktori build

0
SCG82