rsync menyalin hanya beberapa jenis file menggunakan opsi penyertaan

110

Saya menggunakan skrip bash berikut untuk menyalin hanya file dengan ekstensi tertentu (dalam hal ini * .sh), namun masih menyalin semua file. apa yang salah?

dari = $ 1
menjadi = $ 2

rsync -zarv --include = "*. sh" $ dari $ ke
pengguna881480
sumber
4
Meskipun tidak secara tegas terkait, saya sarankan mengutip $ dari / $ ke. Tidak melakukannya dapat memberikan hasil yang tidak diharapkan jika argumen posisi 1/2 menyertakan spasi.
Kjetil Joergensen
apakah Anda mendapatkan pemahaman mengapa perintah Anda tidak berfungsi?
Charlie Parker
@CharlieParker: Apakah Anda harus menggunakan rsync, ini dapat dicapai dengan sangat baik dengan internal shell?
Inian
Apa kekurangan dari pertanyaan ini dan jawabannya adalah bagaimana membuat perintah jika saya memiliki direktori rekursif yang ingin saya kirim hanya satu jenis file. Tampaknya itu hanya melakukannya untuk direktori target ...
Charlie Parker

Jawaban:

200

Saya pikir --includedigunakan untuk menyertakan subset file yang dikecualikan oleh --exclude, daripada hanya menyertakan file-file itu. Dengan kata lain: Anda harus memikirkan tentang memasukkan makna, jangan mengecualikan .

Coba saja:

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

Untuk rsync versi 3.0.6 atau lebih tinggi, urutan perlu dimodifikasi sebagai berikut (lihat komentar):

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

Menambahkan -mbendera akan menghindari pembuatan struktur direktori kosong di tujuan. Diuji dalam versi 3.1.2.

Jadi jika kita hanya ingin file * .sh kita harus mengecualikan semua file --exclude="*", termasuk semua direktori --include="*/"dan menyertakan semua file * .sh --include="*.sh".

Anda dapat menemukan beberapa contoh bagus di bagian Sertakan / Kecualikan Aturan Pola di halaman manual

chepner
sumber
10
Meskipun itu akan memberi Anda semua sub-direktori, jika ada file .sh di subdirektori yang ingin Anda rsync, kemungkinan Anda juga ingin menggunakan --include = "* /".
Kjetil Joergensen
50
Saya mencoba ini di rsync versi 3.0.7, yang saya dapatkan sejak lama dari macports, dan itu tidak berfungsi dengan urutan include / excludes ini. Ini adalah apa yang saya berakhir dengan yang bekerja untuk saya (diadaptasi untuk OP): rsync -zarv --include="*/" --include="*.sh" --exclude="*" "$from" "$to".
Bijou Trouvaille
3
Saya mencoba dengan rsync 3.0.9 dan tidak berhasil. Bijou benar, --include=\*.sh--exclude=\*
urutannya
3
Perhatikan bahwa Anda selalu dapat mengeklik edit dan menyarankan edit untuk jawabannya :)
Achal Dave
2
Ini tidak berfungsi dengan urutan penyertaan / pengecualian Anda, tetapi berfungsi dengan urutan yang disarankan oleh Bijou Trouvaille
John Smith Opsional
57

Jawaban oleh @chepner akan menyalin semua sub-direktori terlepas dari fakta apakah itu berisi file atau tidak. Jika Anda perlu mengecualikan sub-direktori yang tidak berisi file dan masih mempertahankan struktur direktori, gunakan

rsync -zarv  --prune-empty-dirs --include "*/"  --include="*.sh" --exclude="*" "$from" "$to"
WanderingMind
sumber
1
Ini adalah persyaratan bagi saya: "Jika Anda perlu mengecualikan sub-direktori yang tidak berisi file dan masih mempertahankan struktur direktori" +1
Juuso Ohtonen
1
Saya tidak mengerti bagaimana Anda tahu apa urutan --includes?
Charlie Parker
1
Bagaimana seseorang membuat perintah jika saya memiliki direktori rekursif yang ingin saya kirim hanya satu jenis file. Tampaknya itu hanya melakukannya untuk direktori target.
Charlie Parker
15

Satu lagi tambahan: jika Anda perlu menyinkronkan file dengan ekstensinya dalam satu dir saja (tanpa rekursi) Anda harus menggunakan konstruksi seperti ini:

rsync -auzv --include './' --include '*.ext' --exclude '*' /source/dir/ /destination/dir/

Perhatikan titik di awal --include. --no-rtidak berfungsi dalam konstruksi ini.

EDIT:

Terima kasih kepada gbyte.co untuk komentarnya yang berharga!

Serge Roussak
sumber
1
bagaimana Anda tahu bagaimana urutan bendera itu dan apa yang perlu disertakan?
Charlie Parker
1
@CharlieParker, karena rsync menggunakan opsi includedan excludedalam urutan yang ditentukan. Selain itu , rsync berhenti pada opsi pertama yang cocok. Jadi, jika kita menentukan --exclude '*'tempat pertama dalam contoh ini, rsync tidak akan melakukan apa-apa. Temui pria itu untuk penjelasan lebih lanjut.
Serge Roussak
bisakah Anda menjelaskan kepada saya apa yang dilakukan setiap bendera? Bendera pertama -- include './' mengatakan sertakan semua yang ada di jalur direktori sumber? Kemudian yang berikutnya `--include '.ext'` menyertakan file tertentu di jalur sumber bernama .extdan kemudian exclude mengatakan jangan kirim yang lain --exclude '*'? Apakah itu benar?
Charlie Parker
1
Bagaimana seseorang membuat perintah jika saya memiliki direktori rekursif yang ingin saya kirim hanya satu jenis file. Tampaknya itu hanya melakukannya untuk direktori target.
Charlie Parker
1
Terima kasih untuk ini! Perlu --include '*.ext'dan tidak--include '.ext'
gbyte
13

Inilah bagian penting dari halaman manual:

Karena daftar file / direktori yang akan ditransfer dibuat, rsync memeriksa setiap nama yang akan ditransfer terhadap daftar pola sertakan / kecualikan secara bergantian, dan pola pencocokan pertama dijalankan: jika itu adalah pola pengecualian, maka file itu adalah dilewati; jika itu adalah pola penyertaan maka nama file itu tidak akan dilewati; jika tidak ditemukan pola yang cocok, maka nama file tidak akan dilewati.

Untuk meringkas:

  • Tidak cocok dengan pola apa pun berarti file akan disalin!
  • Algoritme berhenti setelah ada pola yang cocok

Juga, sesuatu yang diakhiri dengan garis miring adalah direktori yang cocok (seperti find -type dakan).

Mari kita pisahkan jawaban ini dari atas.

rsync -zarv  --prune-empty-dirs --include "*/"  --include="*.sh" --exclude="*" "$from" "$to"
  1. Jangan melewatkan direktori apa pun
  2. Jangan lewatkan .shfile apa pun
  3. Lewati semuanya
  4. (Secara implisit, jangan lewatkan apa pun, tetapi aturan di atas mencegah aturan default tidak pernah terjadi.)

Akhirnya, --prune-empty-directoriesmenjaga aturan pertama dari membuat direktori kosong di semua tempat.

Jim Hunziker
sumber
Terima kasih banyak telah menjelaskan apa yang terjadi. Sekarang ada kemungkinan lebih baik bahwa saya tidak akan melupakan perintah itu.
MohamedEzz
3
"Algoritme berhenti setelah pola apa pun cocok" - ini adalah kuncinya, dan tidak ada jawaban yang berperingkat lebih tinggi yang menjelaskannya sejelas dan sejelas yang Anda lakukan di sini. Tentu saja ini ada di halaman manual di sana, dan jika saya Saya sudah membaca semuanya dengan cermat, saya sudah melihatnya. Tetap saja, terima kasih.
TheDudeAbides
0

Jika seseorang mencari ini ... Saya hanya ingin melakukan rsync file dan folder tertentu dan berhasil melakukannya dengan perintah ini: rsync --include-from=rsync-files

Dengan file rsync:

my-dir/
my-file.txt

- /*
Pascal Polleunus
sumber
0

Tulis fungsi praktis ini dan masukkan skrip bash saya atau ~/.bash_aliases. Menguji sinkronisasi secara lokal di Linux dengan bash dan awkdiinstal. Berhasil

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:

singkat praktis dan dapat diperluas ketika seseorang ingin menambahkan lebih banyak argumen (yaitu --dry-run).

Contoh:

selrsync 'tsv,csv' ./source ./target --dry-run
biocyberman
sumber