rsync โดยใช้ regex เพื่อรวมเฉพาะบางไฟล์


11

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

$ rsync -avvz --include ='*/' --include='.*[Nn][Aa][Mm][E].*' --exclude='*' ./a/ ./b/

ไม่มีการคัดลอกอะไรเลยผลลัพธ์ของ debug จะแสดง:

[sender] hiding file 1Name.txt because of pattern *
[sender] hiding file 1.txt because of pattern *
[sender] hiding file 2.txt because of pattern *
[sender] hiding file Name1.txt because of pattern *
[sender] hiding directory test1 because of pattern *
[sender] hiding file NaMe.txt because of pattern *

ฉันได้ลองใช้: --include='*[Nn][Aa][Mm][E]*'และชุดค่าผสมอื่น ๆ แต่ก็ยังไม่ได้ไป

มีแนวคิดใดบ้างเกี่ยวกับวิธีใช้ regex เพื่อรวมไฟล์บางไฟล์?


4
ทำไมคุณกำลังใช้--exclude='*'?

2
ดังนั้นจึงยกเว้นทุกอย่างที่ไม่ได้เป็นส่วนหนึ่งของการรวม

'ซ่อนไฟล์ 1Name.txt เนื่องจากรูปแบบ' สิ่งนี้บ่งชี้: - "กฎนั้น - ต้องรวมอยู่ในคำสั่งหรือไม่" หรือถ้าคุณต้องการที่จะแยกบางไฟล์แล้วทำไม " "
Akshay Patil

คำตอบ:


5

rsync ไม่พูด regex คุณสามารถขอความช่วยเหลือค้นหาและ grep แม้ว่ามันจะได้รับความลับเล็ก ๆ น้อย ๆ วิธีค้นหาไฟล์เป้าหมาย:

find a/ |
grep -i 'name'

แต่ทั้งหมดนำหน้าด้วย "a /" - ซึ่งสมเหตุสมผล แต่สิ่งที่เราต้องการท้ายคือรายการของรูปแบบรวมที่ยอมรับได้สำหรับ rsync และเนื่องจากคำนำหน้า "a /" ใช้ไม่ได้สำหรับ rsync I ' จะลบด้วยการตัด:

find . |
grep -i 'name' |
cut -d / -f 2-

ยังมีปัญหาอยู่ - เราจะยังคงพลาดไฟล์ในไดเรกทอรีย่อยเนื่องจาก rsync ไม่ค้นหาไดเรกทอรีในรายการที่แยก ฉันจะใช้ awk เพื่อเพิ่มไดเรกทอรีย่อยของไฟล์ที่ตรงกันในรายการรูปแบบรวม:

find a/ |
grep -i 'name' |
cut -d / -f 2- |
awk -F/ '{print; while(/\//) {sub("/[^/]*$", ""); print}}'

สิ่งที่เหลืออยู่คือการส่งรายการไปยัง rsync - เราสามารถใช้อาร์กิวเมนต์ --include-from = - เพื่อจัดทำรายการรูปแบบไปยัง rsync ในอินพุตมาตรฐาน ดังนั้นทั้งหมด:

find a/ |
grep -i 'name' |
cut -d / -f 2- |
awk -F/ '{print; while(/\//) {sub("/[^/]*$", ""); print}}' |
rsync -avvz --include-from=- --exclude='*' ./a/ ./b/

โปรดทราบว่าไดเรกทอรีต้นทาง 'a' ถูกอ้างถึงผ่านสองเส้นทางที่ต่างกัน - "a /" และ "./a/" นี่มันบอบบาง แต่สำคัญ เพื่อให้สิ่งต่าง ๆ สอดคล้องกันมากขึ้นฉันจะทำการเปลี่ยนแปลงขั้นสุดท้ายและอ้างถึงไดเรกทอรีต้นทางเป็น "./a/" เสมอ อย่างไรก็ตามนี่หมายความว่าคำสั่ง cut ต้องเปลี่ยนเนื่องจากจะมี "./" พิเศษที่ด้านหน้าของผลลัพธ์จากการค้นหา:

find ./a/ |
grep -i 'name' |
cut -d / -f 3- |
awk -F/ '{print; while(/\//) {sub("/[^/]*$", ""); print}}' |
rsync -avvz --include-from=- --exclude='*' ./a/ ./b/

พยายามเรียกใช้พบปัญหาเกี่ยวกับคำสั่งตัด ดูเหมือนว่า-tเป็นสวิตช์ที่ถูกต้อง

แก้ไข: ฉันหมายถึง -t ไม่ใช่สวิตช์ที่ถูกต้อง

ขออภัยควรเป็น -d ฉันเริ่มใช้ sed แล้วเปลี่ยนเป็น cut เพราะฉันคิดว่ามันชัดเจน แต่ลืมแก้ไขคำสั่งของฉัน: S

ติดตาม: พยายามแก้ไข scrip เพื่อรับอาร์กิวเมนต์ ($ 1 = path_to_search, $ 2 เป็นรูปแบบสำหรับ egrep) เนื่องจากฉันกำลังจับคู่ชื่อไฟล์และส่วนขยายผสมกัน ส่วนนั้นใช้งานได้ดีฉันได้รับรายการที่คาดหวัง แต่ rsync ล้มเหลวในการคัดลอก ดูเหมือนว่าจะทำงานเฉพาะกับไดเรกทอรีอักขระชื่อเดียวในตัวอย่าง (a) ฉันเดาว่าคำสั่ง cut จะต้องมีการปรับเปลี่ยนเพื่อตัดตัวละครตามผู้ปกครอง / หรือแหล่ง dir? Kinda สูญเสียวิธีการดังกล่าว:
user1957413

ใช่แล้วคุณพูดถูก มันควรจะทำงานกับชื่อไดเรกทอรีของความยาวใด ๆ แต่จะล้มเหลวทันทีที่คุณอ้างถึงไดเรกทอรีนอกไดเรกทอรีปัจจุบัน (เพราะจะมีจำนวนทับที่แตกต่างกันในส่วนคำนำหน้า) ในการแก้ไขปัญหานั้นอาจจะง่ายที่สุดในการใช้ sed แทนที่จะเป็น cut เช่น: sed "s#^$1/*##" buuuut ที่จะแตกบนพา ธ ที่มี # ในการแก้ไขปัญหาที่เราต้องพูดชื่อไดเรกทอรีที่เข้ามา: prefix=$(echo "$1" | sed 's#/#\\/#g')แล้วsed "s/^$prefix\\/*//" subleties ของทุบตีอ้างเป็นบิตของฝันร้าย;)
sqweek

7

ฉันอยากจะแนะนำให้ใช้ตัวเลือกตัวกรองของ rsync สำหรับตัวอย่างของคุณเพียงพิมพ์:

rsync -vam -f'+ *[Nn][Aa][Mm][E]*' -f'+ */' -f'- *' a b

กฎตัวกรองแรกจะบอก rsync ว่าจะรวมรูปแบบใด จำเป็นต้องใช้กฎที่สองเพื่อบอก rsync เพื่อตรวจสอบไดเรกทอรีทั้งหมดในการแวะผ่าน เพื่อป้องกันไม่ให้ dirs ว่างรวมพวกเขาจะถูกแยกออกอย่างชัดเจนโดย-mตัวเลือก กฎตัวกรองล่าสุดบอก rsync ให้กำจัดรูปแบบที่เหลือทั้งหมดที่ยังไม่ตรงกัน


หวาน. สิ่งนี้ใช้ได้เช่นกัน ฉันได้รับโฟลเดอร์ภายในของ b ที่ได้รับการแก้ไขโดยใช้ a / b / เป็นแหล่งที่มาและปลายทาง ขอบคุณ!
user1957413

ใช้ -f '+ * [Nn] [Aa] [Mm] [E] **' (สองดาวในตอนท้าย) เพื่อรวมเนื้อหาของไดเรกทอรีทั้งหมดที่มีชื่อเฉพาะ
phobic

2

หากคุณใช้ ZSH คุณสามารถใช้แฟล็ก (#i) เพื่อปิดความไวของตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ ตัวอย่าง:

$ touch NAME
$ ls (#i)*name*
NAME

ZSH ยังรองรับการยกเว้นซึ่งถูกระบุเช่นเดียวกับพา ธ ปกติ แต่มีค่าเริ่มต้น ~

$ touch aa ab ac
$ ls *~*c
aa ab

คุณสามารถแยกห่วงโซ่:

$ ls *~*c~*b
aa

ในที่สุดคุณสามารถระบุประเภทของไฟล์ที่คุณต้องการคืน (ไดเรกทอรีไฟล์ ฯลฯ ) สิ่งนี้ทำกับ (/) สำหรับไดเรกทอรีและ (.) สำหรับไฟล์

$ touch file
$ mkdir dir
$ ls *(.)
file

จากทั้งหมดนี้ฉันจะทำคำสั่งว่า:

rsync -avvz *(/) (#i)*name* ./a/ ./b/

(ฉันไม่เห็นความจำเป็นในการแยกตัวเลือกเหล่านี้)


1

คำตอบของ @ sqweek ด้านบนนั้นยอดเยี่ยม แต่ฉันสงสัยว่าเขามีข้อบกพร่องในawkสคริปต์ของเขาสำหรับการสร้างไดเรกทอรีหลักเนื่องจากมันให้ฉันเช่น:

$ echo a/b/c/d | awk -F/ '{print; while(/\//) {sub("/[^/]*", ""); print}}'
a/b/c/d
a/c/d
a/d
a

ฉันสามารถแก้ไขได้โดยใช้gensubแทน:

$ echo a/b/c/d | awk -F/ '{print; while(/\//) { $0=gensub("(.*)/[^/]*", "\\1", "g"); print}}'
a/b/c/d
a/b/c
a/b
a

ดังนั้นวิธีการแก้ปัญหาของเขาเต็มไปด้วยการawkเปลี่ยนแปลงเล็กน้อยจะเป็น:

find ./a/ |
grep -i 'name' |
cut -d / -f 3- |
awk -F/ '{print; while(/\//) { $0=gensub("(.*)/[^/]*", "\\1", "g"); print}}' |
rsync -avvz --include-from=- --exclude='*' ./a/ ./b/

ขอบคุณ แก้ไขคำตอบของฉันด้วยการแก้ไขที่เทียบเท่าของการยึด regex ไปยังจุดสิ้นสุดของบรรทัด ( sub("/[^/]*$"))
sqweek

0

พยายามใช้สคริปต์ C # เนื่องจากเป็นภาษาที่ฉันมีประสบการณ์มากที่สุด ฉันสามารถสร้างรายการไฟล์ที่ฉันต้องการรวมได้ แต่บางคน rsync ยังคงบอกว่าฉันจะขึ้นเขา มันสร้างโฟลเดอร์ แต่จะไม่สนใจไฟล์ นี่คือสิ่งที่ฉันได้รับ ..

ก่อนอื่นเนื้อหาของไดเรกทอรี:

~/mono$ ls -l
total 24
drwxr-xr-x 5 me me 4096 Jan 15 00:36 a
drwxr-xr-x 2 me me 4096 Jan 15 00:36 b
drwxr-xr-x 3 me me 4096 Jan 14 00:31 bin
-rw-r--r-- 1 me me 3566 Jan 15 00:31 test.cs
-rwxr-xr-x 1 me me 4096 Jan 15 00:31 test.exe
-rwxr--r-- 1 me me  114 Jan 14 22:40 test.sh

ดังนั้นผลลัพธ์ของสคริปต์ C #:

~/mono$ mono test.exe

/a/myfile/myfileseries.pdf
/a/myfile2/testfile.pdf

และผลลัพธ์การดีบัก:

~/mono$ mono test.exe | rsync -avvvz --include='*/' --include-from=- --exclude='*' ./a/ ./b/
[client] add_rule(+ */)
[client] parse_filter_file(-,20,3)
[client] add_rule(+ /a/myfile/myfileseries.pdf)
[client] add_rule(+ /a/myfile2/testfile.pdf)
[client] add_rule(- *)
sending incremental file list
[sender] make_file(.,*,0)
[sender] hiding file 1Name.txt because of pattern *
[sender] showing directory myfile2 because of pattern */
[sender] make_file(myfile2,*,2)
[sender] hiding file 1.txt because of pattern *
[sender] hiding file 2.txt because of pattern *
[sender] hiding file Name1.txt because of pattern *
[sender] showing directory test1 because of pattern */
[sender] make_file(test1,*,2)
[sender] hiding file NaMe.txt because of pattern *
[sender] showing directory myfile because of pattern */
[sender] make_file(myfile,*,2)
send_file_list done
send_files starting
[sender] hiding file myfile/myfileseries.pdf because of pattern *
[sender] hiding file myfile2/testfile.pdf because of pattern *
[sender] hiding file test1/test.txt because of pattern *

0

[แก้ไข] ใช้งานได้ในพื้นที่เท่านั้น สำหรับเส้นทางระยะไกลโครงสร้างไดเรกทอรีจะต้องสร้างขึ้นก่อน

ง่ายกว่าคำตอบที่ยอมรับได้ ใช้ - ไฟล์จากซึ่งรวมถึงไดเรกทอรีหลักโดยอัตโนมัติและพิมพ์เส้นทางของไฟล์ด้วย% P

find /tmp/source -wholename '*[Nn][Aa][Mm][E]*' -printf '%P\n' | rsync -vzrm --exclude='*/' --files-from=- /tmp/source/ /tmp/target/

ดังนั้นคุณจะต้องใช้และfindrsync

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