`find -name 'pattern ที่ตรงกับหลาย pattern


335

ผมพยายามที่จะได้รับรายชื่อของงูหลามและ HTML find Documents -name "*.{py,html}"ไฟล์ทั้งหมดในไดเรกทอรีที่มีคำสั่ง

จากนั้นตามมาหน้าคน:

การจัดฟันภายในลวดลาย ('{}') ไม่ถือว่าเป็นพิเศษ (นั่นคือ find. -name 'foo {1,2}' ตรงกับไฟล์ชื่อ foo {1,2} ไม่ใช่ไฟล์ foo1 และ foo2

เนื่องจากนี่เป็นส่วนหนึ่งของไปป์ไลน์ฉันต้องการระบุส่วนขยายที่ตรงกับขณะใช้งานจริง (ไม่มีการเข้ารหัส) หากพบว่าไม่สามารถทำเช่นนั้นได้ perl one-liner (หรือคล้ายกัน) ก็น่าจะใช้ได้

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



ยูทิลิตี้ที่มักถูกมองข้ามและใช้งานไม่ได้ก็เช่นlocateกันแม้ว่าจะมีข้อแม้ที่ว่า updatedb ภายในอาจไม่ทันสมัย แต่มันรวดเร็ว
ไมเคิล

ฉันโหวตให้ปิดคำถามนี้เป็นหัวข้อนอกเพราะเป็นของ Unix & Linux
Dan Dascalescu

คำตอบ:


481

ใช้-oซึ่งหมายถึง "หรือ":

find Documents \( -name "*.py" -o -name "*.html" \)

คุณต้องสร้างบรรทัดคำสั่งนั้นโดยทางโปรแกรมซึ่งไม่ใช่เรื่องง่าย

คุณใช้ bash (หรือ Cygwin บน Windows) หรือไม่ หากคุณเป็นเช่นนั้นคุณควรทำสิ่งนี้:

ls **/*.py **/*.html

ซึ่งอาจจะสร้างโปรแกรมได้ง่ายกว่า


3
ฉันกำลังใช้ zsh ซึ่งตามกฎทั่วไปรองรับ bashisms ทั้งหมดบวกกับอีกมาก
Xiong Chiamiov

12
Zsh รองรับ**การค้นหาแบบเรียกซ้ำ ทุบตีสนับสนุนเฉพาะในรุ่น 4.0 shopt -s globstarขึ้นไปและเฉพาะที่มี
ephemient

2
คุณสามารถมี aro ได้กี่ตัว ฉันมีรายการ. gcda (ข้อมูลความครอบคลุม) ที่อาจสร้างขึ้นจำนวนมาก
Jasper Blues

40
คุณจำเป็นต้องล้อมรอบสอง-names -execพร้อมด้วยวงเล็บถ้าคุณกำลังใช้ เช่นfind Documents \( -name "*.py" -o -name "*.html" \) -exec file {} \;
artbristol

2
ความคิดเห็น @artbristol มีความเกี่ยวข้องมากถ้าเช่นคุณกำลังเพิ่ม a -print0เพื่อจัดการชื่อไฟล์ด้วยช่องว่าง
nimrodm

63

บางรุ่นของ find ซึ่งส่วนใหญ่เป็นระบบ linux อาจรองรับตัวเลือกอื่น ๆ เช่น -regex และ -regextype ซึ่งค้นหาไฟล์ที่มีชื่อที่ตรงกับ regex

ตัวอย่างเช่น

find . -regextype posix-egrep -regex ".*\.(py|html)$" 

ควรทำเคล็ดลับในตัวอย่างข้างต้น อย่างไรก็ตามนี่ไม่ใช่ POSIX ฟังก์ชันการค้นหามาตรฐานและขึ้นอยู่กับการใช้งาน


1
intersting แต่ซับซ้อนกว่าคำตอบอื่น ๆ
m1k3y3

12
ง่ายกว่า: ใช้find . -regex ".*\.\(py\|html\)$"งานได้เนื่องจากค้นหาค่าเริ่มต้นสำหรับนิพจน์ทั่วไปของสไตล์ Emacs ซึ่งแตกต่างกันเล็กน้อยดังนั้นคุณไม่จำเป็นต้องระบุชนิด regexty
robru

2
หากคุณมีนิพจน์จำนวนมาก-regextype posix-egrepจะมีประโยชน์ (ไม่เช่นนั้นคุณจะต้องหลีกเลี่ยงอักขระจำนวนมาก) นี่คือคำสั่ง find ที่ฉันใช้สำหรับการสร้าง dist-hook zip การกระจาย Windows (ค้นหาไฟล์ที่จะเปลี่ยนและในไฟล์จะเปลี่ยนเป็น dos-eol): find -regextype posix-egrep -regex ".*(\.([chyl]|def|cpy|cob|conf|cfg)|(README|ChangeLog|AUTHORS|ABOUT-NLS|NEWS|THANKS|TODO|COPYING.*))$" -exec sed -i -e 's/\r*$/\r/' {} \;
Simon Sobisch

32

คุณสามารถเพิ่มส่วน-nameคำสั่งได้โดยทางโปรแกรมโดยคั่นด้วย-or:

find Documents \( -name "*.py" -or -name "*.html" \)

หรือไปวนซ้ำง่ายๆแทน:

for F in Documents/*.{py,html}; do ...something with each '$F'... ; done

@ user2284570: จากนั้นอาจไม่มี *.pyfindไฟล์หรือคุณมีบางรุ่นคี่ คำสั่งข้างต้นใช้ได้ผลดี
Stephan202

ไม่ฉันใช้-inameอยู่ มันจะส่งคืน*.pyไฟล์เฉพาะเมื่อเขียนมันในตำแหน่งสุดท้าย(เช่นiname *.htmlคือการแสดงออกครั้งแรก) ฉันใช้คำสั่งกับ Debian
2284570

คุณใช้เครื่องหมายคำพูด? นั่นสำคัญมาก
Stephan202

1
มันเป็นหรือ - หรือ -o?
Stephane

1
@StephaneEybert: ใช้ได้ แต่อย่างหลังเท่านั้นที่เป็นไปตาม POSIX (ตามหน้า man)
Stephan202

16

จะพบไฟล์. c หรือ. cpp ทั้งหมดบน linux

$ find . -name "*.c" -o -name "*.cpp"

คุณไม่จำเป็นต้องใช้วงเล็บในการหลบหนียกเว้นว่าคุณกำลังทำ mods เพิ่มเติมอยู่ ที่นี่จากหน้า man ที่พวกเขาบอกว่าถ้ารูปแบบตรงกันให้พิมพ์ บางทีพวกเขากำลังพยายามควบคุมการพิมพ์ ในกรณีนี้การพิมพ์จะทำหน้าที่เป็นเงื่อนไขและกลายเป็นเงื่อนไข "และ" มันจะป้องกันไม่ให้ไฟล์. c ใด ๆ ถูกพิมพ์

$ find .  -name "*.c" -o -name "*.cpp"  -print

แต่ถ้าคุณชอบคำตอบดั้งเดิมคุณสามารถควบคุมการพิมพ์ได้ นี่จะค้นหาไฟล์. c ทั้งหมดเช่นกัน

$ find . \( -name "*.c" -o -name "*.cpp" \) -print

หนึ่งตัวอย่างสุดท้ายสำหรับไฟล์ต้นฉบับ c / c ++

$ find . \( -name "*.c" -o -name "*.cpp"  -o -name "*.h" -o -name "*.hpp" \) -print

11

ฉันมีความต้องการที่คล้ายกัน สิ่งนี้ใช้ได้กับฉัน:

find ../../ \( -iname 'tmp' -o -iname 'vendor' \) -prune -o \( -iname '*.*rb' -o -iname '*.rjs' \) -print

3
สมบูรณ์ แต่ฉันคิดว่ามันแปลกเล็กน้อยที่ไม่สามารถทำงานได้โดยไม่ต้อง()
pedrofurla

ฉันต้องการค้นหาไฟล์ที่ตรงกับ * .c * .cpp หรือ * .cc ด้วยรูปแบบชื่อเพียงสองชื่อฉันไม่ต้องการ parens แต่ด้วยรูปแบบสามชื่อร่วมกับรูปแบบสอง -o find -name "*.cpp" -o -name "*.c" -o -name "*.cc" -print0ฉันต้องใช้ parens คู่กับ กลุ่มที่สองหรือผู้ประกอบการ find -name "*.cpp" -o \( -name "*.c" -o -name "*.cc" \) -print0อาจเป็นได้ว่า -print0 ซึ่งมักจะเป็น "จริง" ส่งผลต่อตรรกะ
ชายคนนี้พื้นที่คาร์ฟ

5

ค่าเริ่มต้นของฉันคือ:

find -type f | egrep -i "*.java|*.css|*.cs|*.sql"

เช่นเดียวกับการประมวลผลที่ไม่ซับซ้อนfindโดย Brendan Long และ Stephan202 และคณะ:

find Documents \( -name "*.py" -or -name "*.html" \)


3
นั่นไม่ใช่การใช้egrepregexp ที่ถูกต้องแต่คุณมีเปลือกกลมที่ควรใช้ regexp (นอกจากนี้โดยทั่วไปfindการใช้งาน: find {directory} [options...] [action]ที่ขึ้นอยู่กับ Impl, directoryอาจจะเริ่มต้น.และactionค่าเริ่มต้น-printแต่ฉันจะมีความชัดเจน.) ดังนั้นแทนที่จะใช้สิ่งที่ชอบfind . -type f -print | egrep -i '\.java$|\.css$|\.cs$|\.sql$' แต่ยังเป็นไปอย่างรวดเร็วทางเลือกที่findหนึ่งอาจจะยัง ลองlocateในลักษณะคล้าย (แม้จะไม่จำเป็นต้องถึงวันเพราะมัน queries ฐานข้อมูลภายในสำหรับรายการแฟ้ม)
ไมเคิล

2
#! /bin/bash
filetypes="*.py *.xml"
for type in $filetypes
do
find Documents -name "$type"
done

เรียบง่าย แต่ใช้งานได้ :)


1

ฉันต้องการลบไฟล์ทั้งหมดในไฟล์ย่อยของเด็กยกเว้นไฟล์บางไฟล์ การทำงานต่อไปนี้สำหรับฉัน (ระบุสามรูปแบบ):

find . -depth -type f -not -name *.itp -and -not -name *ane.gro -and -not -name *.top -exec rm '{}' +

1

ต้องใช้วงเล็บปีกกาในรูปแบบ\(\)สำหรับรูปแบบชื่อด้วยor

find Documents -type f \( -name "*.py" -or -name "*.html" \)

ในขณะที่สำหรับรูปแบบชื่อกับandผู้ประกอบการก็ไม่จำเป็นต้องใช้

find Documents -type f ! -name "*.py" -and ! -name "*.html" 

0

สิ่งนี้ใช้ได้กับ AIX korn เชลล์

find *.cbl *.dms -prune -type f -mtime -1

สิ่งนี้กำลังมองหา*.cblหรือ*.dmsมีอายุ 1 วันในไดเรกทอรีปัจจุบันเท่านั้นโดยข้ามไดเรกทอรีย่อย


0
find MyDir -iname "*.[j][p][g]"
+
find MyDir -iname "*.[b][m][p]"
=
find MyDir -iname "*.[jb][pm][gp]"

2
โปรดทราบว่าหลังจะตรงกับ foo.jmg แต่จะไม่อยู่ในสองอันดับแรก
copper.

0

เกี่ยวกับอะไร

ls {*.py,*.html}

มันจะแสดงรายการไฟล์ทั้งหมดที่ลงท้ายด้วย. py หรือ. html ในชื่อไฟล์

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