ตัวกรอง Rsync: คัดลอกหนึ่งรูปแบบเท่านั้น


128

ฉันกำลังพยายามสร้างไดเรกทอรีที่จะเก็บไฟล์ PDF ทั้งหมดของฉันและรวบรวมจาก LaTeX LaTeXผมชอบการรักษาแต่ละโครงการในโฟลเดอร์ที่แยกต่างหากทั้งหมดตั้งอยู่ในโฟลเดอร์ขนาดใหญ่ที่เรียกว่า ดังนั้นฉันจึงพยายามวิ่ง:

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

ซึ่งควรหาไฟล์ pdf ทั้งหมด~/LaTeX/และโอนไปยังโฟลเดอร์ผลลัพธ์ มันใช้งานไม่ได้ มันบอกฉันว่ามันไม่ตรงกับ " *.pdf" หากฉันไม่ใช้ตัวกรองนี้คำสั่งจะแสดงรายการไฟล์ทั้งหมดในโฟลเดอร์โครงการทั้งหมดภายใต้ LaTeX ดังนั้นจึงเป็นปัญหากับตัวกรอง * .pdf ฉันพยายามแทนที่~/ด้วยพา ธ เต็มไปยังโฮมไดเร็กตอรี่ของฉัน, แต่นั่นไม่มีผลอะไรเลย.

ฉันกำลังใช้ zsh ฉันพยายามทำสิ่งเดียวกันด้วยการทุบตีและแม้จะมีตัวกรองที่ระบุทุกไฟล์เดียวในทุกไดเรกทอรีย่อย ... เกิดอะไรขึ้นที่นี่?

เหตุใด rsync จึงไม่เข้าใจตัวกรอง PDF ของฉันเท่านั้น


ตกลง. ดังนั้นอัปเดต: ไม่ฉันพยายาม

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

และนี่ทำให้ฉันมีรายชื่อไฟล์ทั้งหมด ฉันเดาเพราะทุกอย่างตรงกับรูปแบบแรก ...


เอ่อดูเหมือนว่าคุณจะถูก ... ฉันคิดว่าคำตอบของฉัน (ใช้**รูปแบบของ zsh ) ควรใช้งานได้
Marcel Stimberg

คำตอบ:


248

TL, DR:

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

Rsync คัดลอกแหล่งที่มาไปยังปลายทาง หากคุณส่งผ่าน*.pdfเป็นแหล่งที่มาเชลล์จะขยายสิ่งนี้ไปยังรายการไฟล์ที่มี.pdfนามสกุลในไดเรกทอรีปัจจุบัน ไม่มีการวนซ้ำแบบวนซ้ำเกิดขึ้นเนื่องจากคุณไม่ได้ผ่านไดเรกทอรีใด ๆ เป็นแหล่งข้อมูล

ดังนั้นคุณต้องเรียกใช้rsync -a ~/LaTeX/ ~/Output/แต่มีตัวกรองเพื่อบอก rsync ให้คัดลอก.pdfไฟล์เท่านั้น กฎตัวกรองของ Rsync นั้นดูน่ากลัวเมื่อคุณอ่านคู่มือ แต่คุณสามารถสร้างตัวอย่างจำนวนมากได้ด้วยกฎง่ายๆ

  • การรวมและการยกเว้น:

    • การแยกไฟล์ตามชื่อหรือตามตำแหน่งนั้นเป็นเรื่องง่าย: --exclude=*~, --exclude=/some/relative/location(สัมพันธ์กับอาร์กิวเมนต์แหล่งที่มา, เช่นนี้ไม่รวม~/LaTeX/some/relative/location)
    • ถ้าคุณต้องการเพื่อให้ตรงกับไม่กี่ไฟล์หรือสถานที่รวมถึงพวกเขารวมถึงไดเรกทอรีที่นำไปสู่พวกเขาทุก (ตัวอย่างเช่นด้วย--include=*/) --exclude='*'แล้วไม่รวมส่วนที่เหลือด้วย นี้เป็นเพราะ:
    • หากคุณแยกไดเรกทอรีสิ่งนี้จะแยกทุกอย่างที่อยู่ด้านล่าง ไฟล์ที่ถูกแยกจะไม่ได้รับการพิจารณาเลย
    • หากคุณรวมไดเรกทอรีสิ่งนี้จะไม่รวมเนื้อหาโดยอัตโนมัติ ในรุ่นล่าสุด--include='directory/***'จะทำเช่นนั้น
    • สำหรับแต่ละไฟล์จะใช้กฎการจับคู่แรก (และจะไม่รวมสิ่งใดที่ไม่ตรงกัน)
  • รูปแบบ:

    • หากรูปแบบไม่มี a /จะใช้กับไดเร็กทอรี sans
    • หากรูปแบบลงท้ายด้วย/มันจะใช้กับไดเรกทอรีเท่านั้น
    • หากรูปแบบเริ่มต้นด้วยก็นำไปใช้กับเส้นทางทั้งหมดจากไดเรกทอรีที่ถูกส่งผ่านเป็นอาร์กิวเมนต์ไปยัง/rsync
    • *สตริงย่อยขององค์ประกอบไดเรกทอรีเดียว (เช่นไม่เคยตรงกัน/); **จับคู่สตริงย่อยของพา ธ ใด ๆ
  • หากอาร์กิวเมนต์ต้นฉบับลงท้ายด้วย a /เนื้อหาจะถูกคัดลอก ( rsync -r a/ bสร้างขึ้นb/fooสำหรับทุกคนa/foo) มิฉะนั้นไดเรกทอรีจะถูกคัดลอก ( rsync -r a bสร้างb/a)


ดังนั้นที่นี่เราจำเป็นต้องรวม*.pdfรวมไดเรกทอรีที่มีพวกเขาและแยกทุกอย่างอื่น

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

โปรดทราบว่าสิ่งนี้จะคัดลอกไดเรกทอรีทั้งหมดแม้แต่ไดเรกทอรีที่ไม่มีไฟล์ที่ตรงกันหรือไดเรกทอรีย่อยที่มีหนึ่งไดเรกทอรี สิ่งนี้สามารถหลีกเลี่ยงได้ด้วย--prune-empty-dirsตัวเลือก (ไม่ใช่วิธีการแก้ปัญหาสากลเนื่องจากคุณไม่สามารถคัดลอกไดเรกทอรีได้โดยการจับคู่อย่างชัดเจน แต่เป็นข้อกำหนดที่หายาก)

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

ตรงกันข้ามกับโซลูชันของฉัน (ใช้**รูปแบบของ zsh ) สิ่งนี้จะสร้างโครงสร้างไดเรกทอรีใหม่ใน dir เป้าหมาย ฉันไม่แน่ใจว่านี่คือสิ่งที่ OP ต้องการหรือไม่
Marcel Stimberg

ฉันต้องการรวมเพียงไดเรกทอรีเดียวและไม่รวมไดเรกทอรีอื่น ๆ ใน/etc/lsyncd/lsyncd.conf.luaไฟล์ มีความคิดอะไรบ้าง?
Dhaduk Mitesh

@DhadukMitesh ฉันไม่คุ้นเคยกับ lsyncd คุณควรถามคำถามนี้เป็นคำถามใหม่
Gilles

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

ค่าเริ่มต้นคือการรวมทุกอย่างดังนั้นคุณต้องแยกอย่างชัดเจนทุกอย่างหลังจากรวมไฟล์ที่คุณต้องการถ่ายโอน ลบ --dry-run เพื่อถ่ายโอนไฟล์จริง

หากคุณเริ่มต้นด้วย:

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

จากนั้นการจับคู่โลภจะแยกทุกอย่างออกทันที

ถ้าคุณลอง:

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

จากนั้นจะโอนเฉพาะไฟล์ PDF ในโฟลเดอร์ระดับบนสุด มันจะไม่ติดตามไดเรกทอรีใด ๆ เนื่องจากถูกยกเว้นโดย '*'


2
ในฐานะของ 2014/03/17 นี้เป็นคำตอบที่ดีที่สุดเท่าที่จะแก้โปสเตอร์เดิมถามว่า กรุณาโหวตมันขึ้น! หากคุณเพิ่ม--prune-empty-dirs(หรือทางลัด-m) คุณยังต้องสำรองไดเรกทอรีว่างเปล่าจำนวนมากที่ปลายทางยกเว้นว่าคุณต้องการให้พวกเขาเป็นตัวเตือนหรือพิมพ์เขียวเชิงโครงสร้าง
porg

1
คำตอบที่ดีที่สุด --include = "* /" คือกุญแจ
Martin Konicek

ฉันต้องการรวมเพียงไดเรกทอรีเดียวและไม่รวมไดเรกทอรีอื่น ๆ ใน/etc/lsyncd/lsyncd.conf.luaไฟล์ มีความคิดอะไรบ้าง?
Dhaduk Mitesh

15

หากคุณใช้รูปแบบเช่น*.pdfนั้นเชลล์“ ขยาย” รูปแบบนั้นนั่นคือแทนที่รูปแบบที่มีการจับคู่ทั้งหมดในไดเรกทอรีปัจจุบัน คำสั่งที่คุณกำลังใช้งาน (ในกรณีนี้ rsync) ไม่ทราบว่าคุณพยายามใช้รูปแบบ

เมื่อคุณใช้zshมีวิธีแก้ปัญหาง่าย ๆ แม้ว่า: **รูปแบบสามารถใช้เพื่อจับคู่โฟลเดอร์แบบเรียกซ้ำ ลองสิ่งนี้:

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

จะไม่คัดลอกไฟล์ PDF ทั้งหมดจากที่อื่น ๆ ในไดเรกทอรีปัจจุบันและทุกอย่างจาก ~ / LaTeX / ถึง ~ / Output หรือไม่
SamB

ฉันเดาว่าคุณหมายถึงrsync -avn ~/LaTeX/**/*.pdf ~/Outputแต่โซลูชันด้วย--includeนั้นสามารถปรับขยายได้มากกว่านี้
Adam Byrtek

ขออภัยแก้ไขคำสั่งที่ฉันพิมพ์ผิดอย่างเร่งด่วน ... ฉันยอมรับว่าคำสั่ง include (ในเวอร์ชันของ SamB) นั้นดีกว่าแม้ว่ามันจะซับซ้อนและเฉพาะสำหรับ rsync มากขึ้นเล็กน้อยในขณะที่สถานการณ์**อาจมีประโยชน์ในสถานการณ์อื่นเช่นกัน
Marcel Stimberg

1
Bash 4 ได้ใช้คุณสมบัติเดียวกัน โอ้และคุณไม่ต้องการ rsync ที่นี่ cp จะทำ ในบางระบบหากมีไฟล์จำนวนมากจะช่วยcd ~/Latex && cp -p **/*.pdf ~/Outputให้หลีกเลี่ยงข้อผิดพลาด "บรรทัดคำสั่งยาวเกินไป"
Gilles

1
โปรดทราบว่ารูปแบบของ rsync ที่ใช้ในตัวกรองการรวมและการแยกยังมี ** ที่ทำสิ่งเดียวกัน คุณสามารถหลบหนี * จากเปลือกหอยอื่น ๆ โดยใส่ไว้ในเครื่องหมายคำพูด
Dan Pritts

13

คุณสามารถใช้findและรายการไฟล์ขั้นกลาง ( files_to_copy) เพื่อแก้ไขปัญหาของคุณ ตรวจสอบให้แน่ใจว่าคุณอยู่ในไดเรกทอรีหลักแล้ว:

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

ทดสอบกับทุบตี


ผมคิดว่าพบว่าเป็นโซลูชั่นที่มีประสิทธิภาพมากที่สุด แต่ผมจะเลือกอย่างใดอย่างหนึ่งใช้พบตัวเลือกหรือการใช้-exec xargsสิ่งที่ต้องการ:find LaTeX/ -type f -iname "*.pdf" -print0 | xargs -0 -i rsync -avn {} Output/
Steven D

ใช่ ... ฉันขอแนะนำให้ค้นหาเช่นกัน ... แม้ว่าฉันจะจินตนาการว่า rsync จะต้องสามารถทำได้
เกบ

นี่เป็นทางออกที่เรียบร้อยสำหรับปัญหาที่ยากขึ้นเช่นกัน: ฉันสามารถใช้สิ่งนี้เพื่อแยกไฟล์ที่มีคลาสเอกสารstandaloneหรือ.texไฟล์ที่ไม่มีชื่อเดียวกันเนื่องจากไฟล์เหล่านี้จะเป็นรูปภาพที่รวมอยู่ในเอกสารบางส่วน ...
เชมัส

2
ตัวเลือก rsync --files-fromยอมรับการอ่านจาก stdin สิ่งนี้จะใช้ได้ find LaTeX/ -type f -a -iname "*.pdf" | rsync -avn --files-from=- ~/ ~/Output/
Juan Calero

9

ตัดสินโดยส่วน "รวม / กฎการยกเว้นรูปแบบ" ของmanpageวิธีการทำเช่นนี้คือ

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

ความแตกต่างที่สำคัญระหว่างคำตอบนี้กับคำตอบของ kbrd คือการ--include="*/"ตั้งค่าสถานะซึ่งบอก rsync ให้ดำเนินการต่อไปและคัดลอกไดเร็กทอรีใด ๆ ที่พบไม่ว่าจะมีชื่ออะไร สิ่งนี้มีความจำเป็นเนื่องจาก rsync จะไม่เรียกเก็บเงินคืนในไดเรกทอรีย่อยเว้นแต่จะได้รับคำแนะนำให้คัดลอกไดเรกทอรีย่อยนั้น

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

  1. ประสบความสำเร็จและทำให้ตัวกรองของคุณยุ่งเหยิง (ไม่น่าจะอยู่กลางธงเช่นนั้นแม้ว่าคุณจะไม่มีทางรู้ว่าใครบางคนจะสร้างไฟล์ชื่อ--include=foo.pdf... )

  2. ล้มเหลวและอาจเกิดข้อผิดพลาดแทนการรันคำสั่ง (ตามที่คุณค้นพบ zsh โดยค่าเริ่มต้น)


ดังนั้นจะคัดลอกเฉพาะ PDF และโครงสร้างไดเรกทอรีในขณะที่ kbrd จะคัดลอกไฟล์ แต่ไม่สนใจโครงสร้างหรือไม่
เชมัส

1
อืมมม นี้ที่จริงยังดูเหมือนว่าจะพยายามคัดลอกทุกอย่างที่ผมคิดว่าเพราะนั่นคือสิ่งที่มันไม่ได้โดยไม่ต้องกรองเพื่อให้includeไอเอ็นจีสิ่งที่พิเศษอยู่แล้วในนั้นไม่ได้เปลี่ยนแปลงอะไร ถ้าคุณเห็นสิ่งที่ฉันหมายถึง ...
เชมัส

7
คุณต้องการ--exclude="*"หลังจาก--include="*.pdf"หรือสิ่งนี้จะโอนทุกอย่าง
jmanning2k

@ jmanning2k: อา ดีแล้วที่รู้!
SamB

4

เกี่ยวกับสิ่งนี้:

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

ไม่man rsyncใส่ตัวกรองหลังจากตัวเลือกและก่อนแหล่งที่มา / ปลายทาง ฉันลองมันแล้วมันใช้งานไม่ได้
เชมัส

วิธีของคุณค้นหาไฟล์. pdf ในโฟลเดอร์ปัจจุบัน แต่ไม่ซ้ำตามที่ฉันต้องการ ( aตัวเลือกสำหรับการเก็บถาวรและเหนือสิ่งอื่นใดมันทำให้การคัดลอกซ้ำ
Seamus

1
โอ้ฉันไม่ดี ฉันปรับปรุงคำตอบของฉัน
kbyrd

+1 ที่อยู่ใกล้มากและให้เบาะแสเกี่ยวกับวิธีการค้นหาเนื้อหาที่เกี่ยวข้องในหน้าคู่มือ (หวังว่าฉันจะเข้าใจถูกต้อง :-)
SamB

3

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

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

ดังนั้นคุณต้องใช้คำสั่งดังต่อไปนี้:

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

สังเกตรูปแบบ "**. pdf" ตามหน้าคน :

หากรูปแบบมี / (ไม่นับต่อท้าย /) หรือ "**" ก็จะจับคู่กับชื่อพา ธ เต็มรวมถึงไดเรกทอรีชั้นนำใด ๆ หากรูปแบบไม่มี / หรือ "**" แสดงว่ารูปแบบนั้นถูกจับคู่กับส่วนประกอบสุดท้ายของชื่อไฟล์เท่านั้น (โปรดจำไว้ว่าอัลกอริทึมจะถูกเรียกใช้ซ้ำดังนั้น "ชื่อไฟล์แบบเต็ม" สามารถเป็นส่วนหนึ่งส่วนใดของเส้นทางจากไดเรกทอรีเริ่มต้นลง

ในการทดสอบขนาดเล็กของฉันสิ่งนี้จะทำงานซ้ำลงในไดเรกทอรีต้นไม้และเลือกเฉพาะไฟล์ PDF


คุณทดสอบยังไงกันแน่? ตามความเข้าใจของฉันของเอกสารและการตรวจสอบการทดลองของฉันคำสั่งของคุณควรคัดลอก*.pdfในไดเรกทอรีระดับบนสุดเท่านั้น (แต่ไม่ใช่~/LaTeX/foo/bar.pdf)
Gilles

@Gilles Crud คุณพูดถูก ฉันสาบานว่าฉันทดสอบสิ่งนี้และใช้งานได้ แต่ฉันไม่สามารถสร้างมันขึ้นมาใหม่ได้ และตอนนี้ที่ฉันอ่านหน้าจริงที่ฉันยกมามันทำให้รู้สึกว่ามันใช้งานไม่ได้ บ่น.
Steven D

1
ฉันก็เข้าใจว่าการทดสอบของฉันผิดตรงไหน "การทดสอบขนาดเล็ก" ของฉันอยู่ในไดเรกทอรีที่มีไฟล์. tex และ. pdf ของฉันเอง ฉันสร้างไดเรกทอรีย่อย "test" และ test.pdf และ test.tex ในส่วนย่อยนั้น อย่างไรก็ตามฉันล้มเหลวที่จะสังเกตเห็นว่ามี test.pdf ใน dir ระดับสูงสุดของฉันน่าจะเป็นเพราะการทดลอง LaTeX อย่างรวดเร็วที่ฉันทำ
Steven D

**ผมก็ยังไม่เข้าใจ คงจะดีถ้ามีตัวอย่าง ;)
buhtz

2

นี่คือทางออกที่ฉันต้องการ:

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

findคำสั่งเป็นเรื่องง่ายที่จะเข้าใจกว่ารวม / ไม่รวมกฎของrsync:-)

หากคุณต้องการคัดลอกเฉพาะไฟล์ PDF เพียงเปลี่ยน.jpgเป็น.pdf

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