คำสั่ง Grep เพื่อค้นหาไฟล์ที่มีสตริงข้อความและย้ายไฟล์เหล่านั้น


15

ฉันสามารถค้นหาไฟล์ในโฟลเดอร์ที่มีสตริงข้อความเฉพาะโดยใช้คำสั่งนี้:

grep -lir 'string' ~/directory/*

ฉันจะย้ายไฟล์ที่ปรากฏในผลลัพธ์ข้างต้นไปยังตำแหน่งอื่นได้อย่างไร


นี่ไง grep -i -Z -r -l 'string' . | xargs -I{} mv {} ./folder_name
Alan Dong

คำตอบ:


10

grep -rและเช่นเคยระวัง -rไม่ใช่ตัวเลือกมาตรฐานและในการใช้งานบางอย่างเช่นทั้งหมด แต่เป็นรุ่นล่าสุดของ GNU grepมันตามลิงค์สัญลักษณ์เมื่อลงจากแผนผังไดเรกทอรีซึ่งโดยทั่วไปแล้วไม่ใช่สิ่งที่คุณต้องการ "บางที่ในแผนผังไดเรกทอรี

ในปรัชญา Unix คุณใช้คำสั่งเพื่อค้นหาไดเรกทอรีสำหรับไฟล์และอีกอันหนึ่งเพื่อดูเนื้อหา

ใช้เครื่องมือ GNU ฉันจะทำ:

xargs -r0 --arg-file <(find . -type f -exec grep -lZi string {} +
  ) mv -i --target-directory /dest/dir

แต่ถึงกระนั้นก็ตามจงระวังสภาวะการแย่งชิงและปัญหาด้านความปลอดภัยที่อาจเกิดขึ้นได้หากคุณเรียกใช้เป็นผู้ใช้รายหนึ่งในไดเรกทอรีที่ผู้ใช้อื่นสามารถเขียนได้


สิ่งนี้ทำให้ฉันพบข้อผิดพลาด: `grep 'ถูกยกเลิกโดยสัญญาณ 13. มีความคิดอะไรผิดปกติหรือไม่
Reena Parekh

@ReenaParekh นั่นจะเป็น SIGPIPE นั่นจะเกิดขึ้นหากxargsออกจากก่อนที่จะอ่านไปยังจุดสิ้นสุดของไฟล์ arg ซึ่งไม่ควรเกิดขึ้นเว้นแต่ว่า xargs จะถูกฆ่าหรือล้มเหลวด้วยเหตุผลใดก็ตามซึ่งในกรณีนี้ฉันคาดว่าคุณจะเห็นข้อผิดพลาดเกี่ยวกับเรื่องนั้นด้วย
Stéphane Chazelas

15

ใช้xargsร่วมกับmvไวยากรณ์ที่สามของ:mv [OPTION]... -t DIRECTORY SOURCE...

grep -lir 'string' ~/directory/* | xargs mv -t DEST

ระวังเกี่ยวกับไฟล์ที่มีตัวอักษรพิเศษ (ช่องว่างคำพูด) หากเป็นกรณีของคุณการกรองรายการด้วยsed(การเพิ่มเครื่องหมายคำพูดรอบชื่อไฟล์ด้วยs/^/'/;s/$/'/) อาจช่วยได้ แต่คุณต้องแน่ใจว่าเครื่องหมายคำพูดเหล่านี้จะไม่ปรากฏในชื่อไฟล์ GNU grepมีตัวเลือก-Z/ --nullเพื่อยกเลิกชื่อไฟล์ NUL

ทางเลือกอื่นสำหรับไวยากรณ์ที่สามที่mvใช้xargsกับสตริงตัวยึดตำแหน่ง ( -I)

ตัวเลือกอื่นคือการทดแทนคำสั่ง - $( )หรือ backticks ``(ในทุบตี) ดังกล่าวในคำตอบ ire_and_curses


3
gnu grep สนับสนุนแฟล็ก -Z เพื่อแยกชื่อไฟล์ด้วยอักขระศูนย์ไบต์ซึ่งเมื่อใช้ร่วมกับแฟ
ล็ก

@ChandraRavoori ขอบคุณฉันได้อัปเดตคำตอบแล้ว
เตอร์

7

หากชื่อไฟล์ของคุณไม่มีอักขระพิเศษใด ๆ (ช่องว่างหรือ\[*?) ให้ใช้การแทนคำสั่ง :

mv `grep -lir 'string' ~/directory/*` destination/

Backticks เลิกใช้แล้ว ใช้แบบพกพาอ่านและวางซ้อนกันได้ $ (... ) แทน
ผู้ใช้ที่ไม่รู้จัก

2

ใช้เฉพาะฟีเจอร์ที่ระบุ POSIX และไม่มีข้อสันนิษฐานเกี่ยวกับชื่อไฟล์:

find ~/directory -type f -exec grep -qiF 'string' {} \; -exec mv {} /path/to/dest \;

หมายเหตุ:

คุณพูดว่า "string" ไม่ใช่ "pattern" ดังนั้น -F (การค้นหาสตริงคงที่) ที่grepดูเหมือนจะเหมาะสม

หากไดเรกทอรีปลายทางของคุณอยู่ที่ใดในไดเรกทอรีการค้นหาของคุณคุณอาจมีสภาพการแข่งขันที่ไม่พึงประสงค์

POSIX specs สำหรับ grep

POSIX specs สำหรับ find


นี่อาจเป็นทางออกที่ดีที่สุดสำหรับ Macos / BSD
Ali

0

ใช้GNU ขนาน :

grep -i -Z -r -l 'string' . | parallel 'mv {} destination/{}'

ht / @ lin-dong สำหรับคำตอบเดิมของเขาด้วย xargs


คงจะดีถ้าคุณให้เครดิตคำตอบของ @ lindong ในความคิดเห็นจากเมื่อปีที่แล้ว
roaima

0

- สมมติว่าคุณมีไดเรกทอรีปลายทางเป็น 'ภายนอก' และต้องการย้ายไฟล์ XLS ทั้งหมดคุณสามารถลองคำสั่งด้านล่าง

sudo mv find /var/log/ -type f -name "*.xls"/ ภายนอก /

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