คัดลอกไฟล์เฉพาะประเภทที่รักษาโครงสร้างโฟลเดอร์


108

ฉันมีโครงสร้างโฟลเดอร์ที่มีไฟล์ * .csv กระจายอยู่ทั่วทั้งโฟลเดอร์ ตอนนี้ฉันต้องการคัดลอกไฟล์ * .csv ทั้งหมดไปยังปลายทางอื่นเพื่อรักษาโครงสร้างโฟลเดอร์

มันทำงานได้โดยทำ:

cp --parents *.csv /target
cp --parents */*.csv" /target
cp --parents */*/*.csv /target
cp --parents */*/*/*.csv /target
...

และอื่น ๆ แต่ฉันต้องการจะใช้คำสั่งเดียว

คำตอบ:


126

มีเหตุผลใดที่ผู้คนต่อต้านการใช้งานของการค้นหา-exec? มันมีประโยชน์มาก

find . -name '*.csv' -exec cp --parents \{\} /target \;

รู้จักเครื่องมือของคุณ ;-)


62
อาจเป็นเพราะสิ่งนี้ \ {\} \;
igo

12
'{}'ทำงานได้ดีเช่นกัน
OrangeDog

3
แม้ว่า-execdirจะปลอดภัยกว่า-execเพียงแค่การแทนที่ด้วยอันอื่นไม่ได้รักษาโครงสร้างโฟลเดอร์ไว้ตามที่ต้องการ
Simon Shine

2
ทำไมฉันถึงได้รับข้อความ 'Omitting directory' เมื่อฉันพยายามที่จะคัดลอกมันด้วยคำสั่งของคุณ?
Vicky Dev

4
คุณช่วยอธิบายได้ไหมว่าทำไมเครื่องมือจัดฟันต้องหนีรอดมาที่นี่
Noumenon

46

คุณสามารถใช้rsyncสิ่งนี้ได้

$ rsync -a --prune-empty-dirs --include '*/' --include '*.csv' --exclude '*' source/ target/

หากคุณต้องการเก็บไดเรกทอรีว่างไว้จากแผนผังแหล่งข้อมูลให้ข้าม--prune-empty-dirsตัวเลือก:

$ rsync -a --include '*/' --include '*.csv' --exclude '*' source/ target/

หากคุณไม่ต้องการ symlinks วันที่ปรับเปลี่ยนสิทธิ์ของแฟ้ม, ฯลฯ เจ้าของเก็บรักษาไว้โปรดแทนที่ด้วยการรวมกันของผู้อื่น-a -rlptgoD;-)


1
-m--prune-emty-dirsเป็นทางลัดสำหรับ
Geremia

นอกจากนี้ยัง-Rสามารถเพิ่มตัวเลือกเพื่อคัดลอกโครงสร้างไดเรกทอรีหลักของแหล่งที่มา (เปรียบเทียบคำตอบของฉันที่นี่)
Geremia

-R ใช้ได้สำหรับฉัน! ขอบคุณ
gigi2

32

คุณสามารถใช้findและcpioในโหมดส่งผ่านได้

find . -name '*.csv' | cpio -pdm  /target

นี่จะค้นหาไฟล์. csv ทั้งหมดในไดเรกทอรีปัจจุบันและด้านล่างและคัดลอกไปยัง / target เพื่อรักษาโครงสร้างไดเรกทอรีที่.รูท

ถ้าคุณใช้

find /path/to/files -name '*.csv' | cpio -pdm /target

มันจะค้นหาไฟล์ทั้งหมดใน/path/to/filesและด้านล่างและคัดลอกไปยัง/target/path/to/filesและด้านล่าง


3
ฉันลองคำตอบทั้งหมดจากบนลงล่างนี้และนี่เป็นคำตอบเดียวที่ทำงานในความพยายามครั้งแรก
OscarRyz

21

cpคำสั่งอนุญาตให้ข้อโต้แย้งจากหลายแหล่ง:

cp **/*.csv --parents ../target

ถ้ำ:ฉันใช้ glob ซ้ำที่นี่; นี้เป็นglobstarตัวเลือกในการทุบตีและ 4+ และได้รับการสนับสนุนโดยเริ่มต้นในksh zshglobs ซ้ำไม่ตรงกับไฟล์และโฟลเดอร์ที่ซ่อนและบางการใช้งานที่ปฏิบัติตาม symlinks ขณะที่คนอื่นทำไม่ได้

หากเชลล์ของคุณไม่รองรับ globs ซ้ำหรือหากคุณไม่ต้องการใช้มันคุณสามารถทำสิ่งต่อไปนี้:

  • *.csv */*.csv */*/*.csv */*/*/*.csv - เป็นหลักสูตรที่ซ้ำซ้อนมากและต้องการทราบว่าโครงสร้างไดเรกทอรีของคุณนั้นลึกเพียงใด
  • $(find . -name '*.csv')- สิ่งนี้จะตรงกับไฟล์และโฟลเดอร์ที่ซ่อน findยังสนับสนุนการระบุว่ามีการติดตาม symlink หรือไม่ซึ่งอาจเป็นประโยชน์

นี่คือสิ่งที่ฉันพยายาม (วงกลมซ้ำ) และพบบางอย่าง แต่ไม่ใช่ทั้งหมด? สวยแปลก ๆ ฉันได้รับผลลัพธ์ที่แน่นอนเหมือนกันเมื่อใช้สคริปต์ copyfiles npm แต่ถ้าฉันใช้คำสั่ง find มันจะพบทุกสิ่ง ...
Randyaa

@ Randyaa ฉันต้องการรายละเอียดเพิ่มเติมเกี่ยวกับไฟล์ที่ไม่พบเพื่อช่วยคุณ คุณอาจพบการสนทนาที่นี่และดำเนินการต่อที่นี่เกี่ยวกับพฤติกรรมที่แม่นยำของ glob แบบเรียกซ้ำที่มีประโยชน์
Kyle Strand

1
กลายเป็น glob ซ้ำไม่ได้เปิดใช้งานด้วยเหตุผลบางอย่าง ... ฉันไม่เคยพบสิ่งนี้มาก่อน แต่ฉันแก้ไขด้วยการดำเนินการshopt -s globstarทันทีก่อนที่คำสั่งของฉันและทุกอย่างจะดี ขอบคุณสำหรับการติดตาม!
Randyaa

--parentsเป็นสิ่งที่ฉันกำลังมองหา ขอบคุณ
Josh

17

อันนี้ใช้ได้สำหรับฉัน:

find -name "*.csv" | xargs cp --parents -t /target


คำตอบที่ดีที่สุดด้วยไวยากรณ์ที่ง่ายที่สุด ทำงานได้ดีและจำได้ง่าย ในหลายกรณีfind [things] | xargs [do stuff]มีประสิทธิภาพมาก
นักบินอวกาศทุกวัน

ตกลง ตรงไปตรงมามากเมื่อเทียบกับคำตอบอื่น ๆ
ทิม B

1
แตกถ้าคุณมีช่องว่างในชื่อไฟล์
Michele Piccolini

Spaces @MichelePiccolini ในชื่อไฟล์สามารถจัดการได้และfind -print0 xargs -0
pasztorpisti

8

สมมติว่าคุณต้องการทำซ้ำโครงสร้างนี้จาก./sourceถึง./destination:

cd source
find . -name "*.csv" | xargs tar cvf - | (cd ../destination ; tar xfp -)

ฉันเตรียมที่จะนับว่าเป็นหนึ่งบรรทัดcd sourceการเป็นเชลล์ในตัว


2
ฉันไม่คิดว่าเขาหมายถึงคำสั่งเดียว - เพียงแค่ไม่ต้องกังวลเกี่ยวกับตัวอย่างของเขา;)

tarมี-Cตัวเลือกให้หลีกเลี่ยงการเปลี่ยนไดเรกทอรีก่อน
บาร์ต

8

จากrsyncmanpage ของ:

-R, - สัมพันธ์

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

rsync -av /foo/bar/baz.c remote:/tmp/

... สิ่งนี้จะสร้างไฟล์ชื่อ baz.c ใน / tmp / บนเครื่องระยะไกล ถ้าคุณใช้แทน

rsync -avR /foo/bar/baz.c remote:/tmp/

จากนั้นไฟล์ชื่อ /tmp/foo/bar/baz.c จะถูกสร้างขึ้นบนเครื่องระยะไกลโดยเก็บรักษาพา ธ แบบเต็มไว้ องค์ประกอบพา ธ พิเศษเหล่านี้เรียกว่า "ไดเรกทอรีโดยนัย" (เช่น "foo" และไดเรกทอรี "foo / bar" ในตัวอย่างด้านบน)

ดังนั้นสิ่งนี้ก็ใช้ได้เช่นกัน:

rsync -armR --include="*/" --include="*.csv" --exclude="*" /full/path/to/source/file(s) destination/
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.