rsync คัดลอกเฉพาะไฟล์บางประเภทโดยใช้ตัวเลือก include


114

ฉันใช้สคริปต์ทุบตีต่อไปนี้เพื่อคัดลอกเฉพาะไฟล์ที่มีนามสกุลบางไฟล์ (ในกรณีนี้คือ * .sh) แต่มันก็ยังคงคัดลอกไฟล์ทั้งหมด เป็นอะไรไป?

จาก = $ 1
ถึง = $ 2

rsync -zarv --include = "*. sh" $ จาก $ ถึง

4
แม้ว่าจะไม่ได้พูดถึงอย่างเคร่งครัด แต่ฉันขอแนะนำให้อ้างถึง $ จาก / $ ถึง การไม่ทำเช่นนั้นอาจให้ผลลัพธ์ที่ไม่คาดคิดหากอาร์กิวเมนต์ตำแหน่ง 1/2 มีช่องว่าง
Kjetil Joergensen

คุณเข้าใจไหมว่าทำไมคำสั่งของคุณถึงใช้ไม่ได้?
Charlie Parker

@CharlieParker: คุณต้องใช้rsyncสิ่งนี้สามารถทำได้ดีกับเชลล์ภายในหรือไม่?
Inian

สิ่งที่คำถามนี้และคำตอบยังขาดคือวิธีสร้างคำสั่งหากฉันมีไดเรกทอรีแบบเรียกซ้ำที่ฉันต้องการส่งไฟล์เพียงประเภทเดียว ดูเหมือนว่าจะทำเพื่อไดเรกทอรีเป้าหมายเท่านั้น ...
Charlie Parker

คำตอบ:


204

ฉันคิดว่า--includeใช้เพื่อรวมชุดย่อยของไฟล์ที่ถูกยกเว้นโดย--excludeแทนที่จะรวมเฉพาะไฟล์เหล่านั้น ในคำอื่น ๆ : คุณต้องคิดเกี่ยวกับการรวมความหมายไม่ได้ยกเว้นไม่ได้ยกเว้น

ลองแทน:

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

สำหรับ rsync เวอร์ชัน 3.0.6 ขึ้นไปจำเป็นต้องแก้ไขลำดับดังนี้ (ดูความคิดเห็น):

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

การเพิ่ม-mแฟล็กจะหลีกเลี่ยงการสร้างโครงสร้างไดเร็กทอรีว่างในปลายทาง ทดสอบในเวอร์ชัน 3.1.2

ดังนั้นถ้าเราเพียงต้องการไฟล์ .sh * เราต้องแยกไฟล์ทั้งหมด--exclude="*"รวมถึงไดเรกทอรีทั้งหมดและรวมถึงไฟล์--include="*/" .sh * ทั้งหมด--include="*.sh"

คุณสามารถดูตัวอย่างที่ดีได้ในส่วนรวม/ ไม่รวมกฎรูปแบบของหน้าคน


10
แม้ว่าจะทำให้คุณได้รับไดเรกทอรีย่อยทั้งหมด แต่หากมีไฟล์. sh ในไดเร็กทอรีย่อยที่คุณต้องการ rsync มีโอกาสที่คุณจะต้องการใช้ --include = "* /" ด้วย
Kjetil Joergensen

51
ฉันลองสิ่งนี้กับ rsync เวอร์ชัน 3.0.7 ซึ่งฉันได้รับมานานแล้วจาก macports และมันใช้ไม่ได้กับคำสั่งรวม / ไม่รวมนี้ นี่คือสิ่งที่ฉันสิ้นสุดกับที่ทำงานให้ฉัน (เหมาะสำหรับ rsync -zarv --include="*/" --include="*.sh" --exclude="*" "$from" "$to"OP):
Bijou Trouvaille

3
ฉันลองใช้ rsync 3.0.9 แล้วไม่ได้ผล Bijou เป็นสิทธิสั่งซื้อไม่เหมาะสม (ครั้งแรก--include=\*.shแล้ว--exclude=\*)
TrueY

3
โปรดทราบว่าคุณสามารถคลิกแก้ไขและแนะนำการแก้ไขคำตอบได้ตลอดเวลา :)
Achal Dave

2
ใช้ไม่ได้กับการสั่งซื้อรวม / ไม่รวมของคุณ แต่ใช้ได้กับคำสั่งซื้อที่แนะนำโดย Bijou Trouvaille
John Smith Optional

57

คำตอบโดย @chepner จะคัดลอกไดเร็กทอรีย่อยทั้งหมดโดยไม่คำนึงถึงความจริงว่ามีไฟล์หรือไม่ หากคุณต้องการยกเว้นไดเรกทอรีย่อยที่ไม่มีไฟล์และยังคงรักษาโครงสร้างไดเร็กทอรีไว้ให้ใช้

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

1
นี่เป็นข้อกำหนดสำหรับฉัน: "หากคุณต้องการยกเว้นไดเรกทอรีย่อยที่ไม่มีไฟล์และยังคงโครงสร้างไดเรกทอรีไว้" +1
Juuso Ohtonen

1
ฉันไม่เข้าใจว่าคุณรู้ได้อย่างไรว่าลำดับของ - รวมคืออะไร?
Charlie Parker

1
หนึ่งจะสร้างคำสั่งได้อย่างไรหากฉันมีไดเร็กทอรีแบบเรียกซ้ำที่ฉันต้องการส่งไฟล์เพียงประเภทเดียว ดูเหมือนว่าจะทำสำหรับไดเร็กทอรีเป้าหมายเท่านั้น
Charlie Parker

15

อีกอย่างหนึ่ง: หากคุณต้องการซิงค์ไฟล์ตามนามสกุลในdir เดียวเท่านั้น (โดยไม่มีการเรียกซ้ำ) คุณควรใช้โครงสร้างดังนี้:

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

--includeให้ความสนใจของคุณเพื่อจุดในครั้งแรก--no-rไม่ทำงานในการก่อสร้างนี้

แก้ไข:

ขอบคุณ gbyte.co สำหรับความคิดเห็นที่มีค่า!


1
คุณรู้ได้อย่างไรว่าลำดับของธงต้องเป็นอย่างไรและต้องรวมอะไรบ้าง
Charlie Parker

1
@CharlieParker เนื่องจาก rsync ใช้includeและexcludeอ็อพชันตามลำดับที่ระบุไว้นอกจากนี้จะหยุดที่ตัวเลือกแรกที่ตรงกัน ดังนั้นหากเราระบุ--exclude '*'ที่แรกในตัวอย่างนี้ rsync จะไม่ทำอะไรเลย ดูชายคนนี้สำหรับคำอธิบายเพิ่มเติม
Serge Roussak

คุณช่วยอธิบายให้ฉันฟังได้ไหมว่าแต่ละธงทำหน้าที่อะไร แฟล็กแรก-- include './' บอกรวมทุกอย่างในพา ธ ไดเร็กทอรีต้นทาง จากนั้นไฟล์ถัดไป "--include" .ext'` จะรวมไฟล์เฉพาะในเส้นทางต้นทางที่ตั้งชื่อ.extแล้วการยกเว้นระบุว่าอย่าส่งอะไรอีก--exclude '*'? ถูกต้องหรือไม่
Charlie Parker

1
หนึ่งจะสร้างคำสั่งได้อย่างไรหากฉันมีไดเร็กทอรีแบบเรียกซ้ำที่ฉันต้องการส่งไฟล์เพียงประเภทเดียว ดูเหมือนว่าจะทำสำหรับไดเร็กทอรีเป้าหมายเท่านั้น
Charlie Parker

1
ขอบคุณสำหรับสิ่งนี้! ต้องการ--include '*.ext'และไม่--include '.ext'
gbyte

13

นี่คือส่วนสำคัญจากหน้าคน:

เนื่องจากรายการไฟล์ / ไดเร็กทอรีที่จะโอนถูกสร้างขึ้น rsync จะตรวจสอบชื่อแต่ละชื่อที่จะโอนเทียบกับรายการของรูปแบบรวม / ไม่รวมในทางกลับกันและรูปแบบการจับคู่แรกจะถูกดำเนินการ: ถ้าเป็นรูปแบบการยกเว้นไฟล์นั้นจะเป็น ข้าม; หากเป็นรูปแบบการรวมชื่อไฟล์นั้นจะไม่ถูกข้าม หากไม่พบรูปแบบที่ตรงกันจะไม่มีการข้ามชื่อไฟล์

สรุป:

  • ไม่ตรงกับรูปแบบใด ๆ หมายความว่าไฟล์จะถูกคัดลอก!
  • อัลกอริทึมจะหยุดทำงานเมื่อรูปแบบใดตรงกัน

นอกจากนี้สิ่งที่ลงท้ายด้วยเครื่องหมายทับคือการจับคู่ไดเรกทอรี (เช่น find -type d )

ลองแยกคำตอบนี้ออกจากด้านบน

rsync -zarv  --prune-empty-dirs --include "*/"  --include="*.sh" --exclude="*" "$from" "$to"
  1. อย่าข้ามไดเรกทอรีใด ๆ
  2. อย่าข้ามใด ๆ .shไฟล์
  3. ข้ามทุกอย่าง
  4. (โดยปริยายอย่าข้ามอะไรเลย แต่กฎข้างบนป้องกันไม่ให้กฎเริ่มต้นเกิดขึ้น)

สุดท้ายนี้--prune-empty-directoriesจะป้องกันไม่ให้กฎข้อแรกสร้างไดเร็กทอรีว่างทั่วทุกที่


ขอบคุณมากสำหรับการอธิบายว่าเกิดอะไรขึ้น ตอนนี้มีโอกาสที่ดีกว่ามากที่ฉันจะไม่ลืมคำสั่ง
MohamedEzz

3
'' อัลกอริทึมจะหยุดเมื่อรูปแบบใด ๆ ตรงกัน " - นี่เป็นกุญแจสำคัญและไม่มีคำตอบใดที่มีคะแนนสูงกว่าที่อธิบายได้ชัดเจนและตรงไปตรงมาเท่าที่คุณทำที่นี่แน่นอนว่านี่อยู่ในหน้าคนและถ้าฉัน 'd อ่านเรื่องทั้งหมดอย่างละเอียดฉันได้เห็นแล้วยังคงขอบคุณ
TheDudeAbides

0

หากมีคนค้นหาสิ่งนี้ ... ฉันต้องการ rsync เฉพาะไฟล์และโฟลเดอร์ที่ต้องการและจัดการได้ด้วยคำสั่งนี้: rsync --include-from=rsync-files

ด้วยไฟล์ rsync:

my-dir/
my-file.txt

- /*

0

เขียนฟังก์ชันที่มีประโยชน์นี้และใส่สคริปต์ทุบตีของฉันหรือ~/.bash_aliases. ทดสอบการซิงค์ในเครื่องบน Linux ด้วย bash และawkติดตั้ง มันได้ผล

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:

สั้นสะดวกและขยายได้เมื่อต้องการเพิ่มอาร์กิวเมนต์ (เช่น --dry-run )

ตัวอย่าง:

selrsync 'tsv,csv' ./source ./target --dry-run
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.