ฉันจะค้นหาไฟล์ในไดเรกทอรีย่อยทั้งหมดโดยใช้เชลล์แล้วคัดลอกไฟล์เหล่านั้นได้อย่างไร


8

ฉันจะหาไฟล์ * .mp3 ด้วยคำสั่งแบบเรียกซ้ำเช่นเดียวกับls -R *.mp3ในไดเรกทอรีที่มีหลายไดเรกทอรีย่อยและในตอนท้ายให้คัดลอกไฟล์เหล่านี้ในไดเรกทอรีที่ฉันเลือก

ขอบคุณสำหรับการสนับสนุน.

คำตอบ:


14

คำสั่งคือ:

find /path/to/directory -name "*.mp3" -exec cp {} /some/other/dir/ \;

ทางเลือก:

find /path/to/dir/ -name '*.mp3' | xargs cp -t /target/

ตัวอย่าง:

alex@MaD-pc:~/test$ ls
1  2  3
alex@MaD-pc:~/test$ ls 1 2 3
1:
1.txt  2.mp3  3.txt

2:
4.txt  5.mp3  6.txt

3:
alex@MaD-pc:~/test$ find . -name "*.mp3" -exec cp {} 3/ \;
alex@MaD-pc:~/test$ ls 3
2.mp3  5.mp3

สำหรับข้อมูลเพิ่มเติม:

man find

ผู้พิพากษาก็ยอมรับ:find /path/to/dir/ -name '*.c' | xargs cp -t /target/
Oli

ผมเป็นคนหนึ่งในคณะกรรมการตัดสินและผมปฏิเสธการแก้ปัญหานี้ 8-) ขอบคุณสำหรับความคิดเห็นของผมจะเพิ่ม :)
hytromo

1
xargsโดยทั่วไปจะเร็วกว่ามาก ฉันเพิ่งจะทำการทดสอบอย่างรวดเร็วที่นี่หาโหลดไฟล์ c และเรียกใช้ls -lพวกเขา มันคือ 0m2.420s xargsและ 0m25.494s สำหรับ-exec... เห็นได้ชัดว่าในกรณีนี้การcpดำเนินการจะใช้เวลาส่วนใหญ่ดังนั้นมันอาจจะไม่สำคัญ แต่มันก็คุ้มค่าที่จะจดบันทึก
Oli

ฉันขอแนะนำให้เพิ่ม-n`` switch to the คำสั่ง cp` เพื่อหลีกเลี่ยงการเขียนทับในกรณีของชื่อที่ซ้ำกัน (หรือการเขียนสคริปต์ที่ตรวจสอบรายการที่ซ้ำกันก่อนที่จะคัดลอกและเปลี่ยนชื่อเป้าหมายตามความจำเป็น)
Elder Geek

2

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

คุณสามารถปรับเปลี่ยนวิธีที่คุณต้องการโดยเปลี่ยนไดเรกทอรีที่findค้นหาและวางไฟล์ผลลัพธ์ หากไม่มีการระบุไดเรกทอรีfindจะค้นหาทั้งโฟลเดอร์หลัก คุณยังสามารถเปลี่ยนcpเป็นmvหรือคำสั่งอื่น ๆ มันค่อนข้างเร็วเพราะฉันเพิ่งทดสอบกับ.jpgไฟล์3945 ! chmod +x myscriptคัดลอกลงในตัวแก้ไขข้อความบันทึกมันแล้วทำให้ปฏิบัติการโดยการเรียกใช้

#!/bin/bash
# a script to recursively find and copy files to a desired location
find ~/Downloads -type f -iname '*.mp3' -print0 |
while IFS= read -r -d '' f; 
do cp -- "$f" ~/Music ;
done

ที่ Bash wiki ที่ระบุไว้นี้จะแสดงว่ามีประโยชน์อย่างไรที่จะรวมwhileลูปและreadคำสั่งเพื่อประมวลผลเอาต์พุตของfindคำสั่ง; และวิธีที่ฉันทำก็ทำให้แน่ใจได้ว่าสคริปต์จะไม่แตกถ้าชื่อไฟล์มีช่องว่างหรืออักขระอื่น ๆ ที่ไม่คาดคิดหรืออักขระพิเศษ

สำหรับข้อมูลทั่วไปเพิ่มเติมเกี่ยวกับfindคำสั่งใส่ในขั้วman findหรือดูmanpages อูบุนตูออนไลน์ สำหรับการแนะนำที่ดีเกี่ยวกับการใช้งานการค้นหาให้ดูบทความนี้เช่นกัน


ไม่find ~/Downloads -type f -iname '*.mp3' | while read mp3file; do cp "$mp3file" ~/Music; doneง่ายกว่านี้?
steabert

วิธีการของฉันแสดงให้เห็นถึงแนวปฏิบัติที่ดีที่สุดและป้องกันสคริปต์ไม่ให้แตกดังที่บันทึกไว้ในลิงก์ที่ฉันยกมา

ah, ฉันเห็นที่ดูแลจัดการตัวอักษรพิเศษขอบคุณสำหรับการเชื่อมโยง :)
steabert

ฉันขอแนะนำให้เพิ่ม-n`` switch to the คำสั่ง cp` เพื่อหลีกเลี่ยงการเขียนทับในกรณีของชื่อที่ซ้ำกัน (หรือการเขียนสคริปต์ที่ตรวจสอบรายการที่ซ้ำกันก่อนที่จะคัดลอกและเปลี่ยนชื่อเป้าหมายตามความจำเป็น)
Elder Geek
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.