mẫu `find -name` khớp với nhiều mẫu


334

Tôi đã cố gắng để có được một danh sách tất cả các tệp python và html trong một thư mục với lệnh find Documents -name "*.{py,html}".

Sau đó cùng đến trang người đàn ông:

Các dấu ngoặc trong mẫu ('{}') không được coi là đặc biệt (nghĩa là tìm. -Name 'foo {1,2}' khớp với tệp có tên foo {1,2}, không phải tệp foo1 và foo2.

Vì đây là một phần của chuỗi ống, tôi muốn có thể chỉ định tiện ích mở rộng nào phù hợp khi chạy (không có mã hóa cứng). Nếu tìm thấy không thể làm điều đó, một perl liner (hoặc tương tự) sẽ ổn.

Chỉnh sửa: Câu trả lời cuối cùng tôi đã đưa ra bao gồm tất cả các loại tào lao, và cũng hơi dài, vì vậy tôi đã đăng nó như một câu trả lời cho ngứa ban đầu mà tôi đang cố gắng gãi. Hãy thoải mái hack nó lên nếu bạn có giải pháp tốt hơn.



Một tiện ích thường bị bỏ qua và không được sử dụng cũng được locate, mặc dù có cảnh báo rằng bản cập nhật nội bộ có thể không được cập nhật. Nhưng nó nhanh thôi.
michael

Tôi đang bỏ phiếu để đóng câu hỏi này ngoài chủ đề vì nó thuộc về Unix & Linux
Dan Dascalescu

Câu trả lời:


480

Sử dụng -o, có nghĩa là "hoặc":

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

Bạn cần xây dựng dòng lệnh đó theo chương trình, điều này không dễ.

Bạn đang sử dụng bash (hoặc Cygwin trên Windows)? Nếu bạn là, bạn sẽ có thể làm điều này:

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

mà có thể dễ dàng hơn để xây dựng chương trình.


3
Tôi đang sử dụng zsh, như một quy tắc chung, hỗ trợ tất cả các bashism, cộng với nhiều hơn nữa.
Xiong Chiamiov

12
Zsh hỗ trợ **tìm kiếm đệ quy; Bash chỉ hỗ trợ nó trong các phiên bản 4.0 trở lên, và chỉ với shopt -s globstar.
ephemient

2
Bạn có thể có bao nhiêu -o args? Tôi đã có một danh sách các tệp .gcda (dữ liệu bảo hiểm) có khả năng lớn để xây dựng
Jasper Blues

40
Bạn cần bao quanh hai -names bằng dấu ngoặc nếu bạn đang sử dụng -exec. Ví dụ:find Documents \( -name "*.py" -o -name "*.html" \) -exec file {} \;
artbristol

2
Nhận xét @artbristol rất phù hợp nếu, ví dụ, bạn đang thêm một -print0để xử lý tên tệp có dấu cách.
nimrodm

63

Một số phiên bản tìm kiếm, chủ yếu trên các hệ thống linux, có thể trên các phiên bản khác cũng hỗ trợ các tùy chọn -regex và -regextype, tìm các tệp có tên khớp với biểu thức chính quy.

ví dụ

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

nên làm thủ thuật trong ví dụ trên. Tuy nhiên đây không phải là chức năng tìm POSIX tiêu chuẩn và phụ thuộc vào việc triển khai.


1
xen kẽ nhưng phức tạp hơn các câu trả lời khác
m1k3y3

12
Đơn giản hơn: find . -regex ".*\.\(py\|html\)$"điều này hoạt động vì tìm mặc định cho các biểu thức chính quy theo kiểu Emacs, hơi khác một chút, vì vậy bạn không phải chỉ định biểu thức chính quy.
robru

2
Nếu bạn có nhiều biểu thức -regextype posix-egreplà tiện dụng (nếu không, bạn cần phải thoát nhiều ký tự). Đây là lệnh find tôi đã sử dụng để tạo một bản phân phối Windows zip (tìm các tệp để thay đổi và trong tệp thay đổi chúng thành 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

Bạn có thể lập trình thêm nhiều -namemệnh đề, cách nhau bởi -or:

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

Hoặc, đi cho một vòng lặp đơn giản thay thế:

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

@ user2284570: sau đó không có *.pytệp hoặc bạn có một số phiên bản kỳ lạ của find. Các lệnh được liệt kê ở trên chỉ hoạt động tốt.
Stephan202

Không, tôi đang sử dụng -iname. Nó chỉ trả về *.pycác tệp nếu ghi nó ở vị trí cuối cùng ( iname *.htmlbiểu thức đầu tiên cũng vậy) . Tôi sử dụng lệnh trên Debian.
dùng2284570

Bạn đang sử dụng dấu ngoặc kép? Điều đó rất quan trọng.
Stephan202

1
Nó là một hay hay một -o?
Stephane

1
@StephaneEybert: hoặc là tốt, nhưng chỉ cái sau là tuân thủ POSIX (theo trang man).
Stephan202

16

Điều này sẽ tìm thấy tất cả các tệp .c hoặc .cpp trên linux

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

Bạn không cần dấu ngoặc đơn thoát trừ khi bạn đang thực hiện một số mod bổ sung. Ở đây từ trang người đàn ông họ đang nói nếu mẫu phù hợp, in nó. Có lẽ họ đang cố gắng kiểm soát việc in ấn. Trong trường hợp này, -print hoạt động như một điều kiện và trở thành một điều kiện "AND'd". Nó sẽ ngăn chặn bất kỳ tập tin .c nào được in.

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

Nhưng nếu bạn thích câu trả lời ban đầu, bạn có thể kiểm soát việc in ấn. Điều này sẽ tìm thấy tất cả các tập tin .c là tốt.

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

Một ví dụ cuối cùng cho tất cả các tệp nguồn c / c ++

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

11

Tôi có một nhu cầu tương tự. Điều này làm việc cho tôi:

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

3
Hoàn hảo. Nhưng tôi thấy hơi kỳ lạ là nó không hoạt động mà không có()
pedrofurla

Tôi muốn tìm các tệp khớp với * .c * .cpp hoặc * .cc Chỉ với hai mẫu tên, tôi không cần parens nhưng với mẫu ba tên được nối với hai mẫu -o find -name "*.cpp" -o -name "*.c" -o -name "*.cc" -print0tôi phải sử dụng một cặp parens để nhóm thứ hai hoặc toán tử. find -name "*.cpp" -o \( -name "*.c" -o -name "*.cc" \) -print0Có thể là -print0, luôn luôn "đúng" đã ảnh hưởng đến logic.
người đàn ông không gian

5

Mặc định của tôi là:

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

Giống như việc findthực hiện quy trình ít tích cực hơn bởi Brendan Long và Stephan202 và cộng sự:

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


3
đó không phải là cách sử dụng chính xác của egrepregrec, thay vào đó, bạn đã sử dụng shell toàn cầu nơi sử dụng regrec. (Ngoài ra, findcách sử dụng thông thường là : find {directory} [options...] [action], trong đó, tùy thuộc vào impl, directorycó thể mặc định .actionmặc định -print, nhưng tôi sẽ nói rõ.) Vì vậy, thay vào đó, hãy sử dụng một cái gì đó như: find . -type f -print | egrep -i '\.java$|\.css$|\.cs$|\.sql$' Nhưng cũng, thay thế rất nhanh find, người ta cũng có thể thử locatetheo cách tương tự (mặc dù không nhất thiết phải cập nhật, vì nó truy vấn db nội bộ cho danh sách tệp)
michael

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

đơn giản nhưng hiệu quả :)


1

Tôi cần phải xóa tất cả các tệp trong thư mục con ngoại trừ một số tệp. Sau đây làm việc cho tôi (ba mẫu được chỉ định):

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

1

Niềng răng trong mẫu \(\)được yêu cầu cho mẫu tên vớior

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

Trong khi đối với mẫu tên với andtoán tử thì không bắt buộc

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

0

Điều này hoạt động trên vỏ AIX korn.

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

Điều này đang tìm kiếm *.cblhoặc *.dmslà 1 ngày tuổi, chỉ trong thư mục hiện tại, bỏ qua các thư mục con.


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

2
Lưu ý rằng cái sau sẽ khớp với foo.jmg nhưng cả hai thứ trên sẽ không.
đồng.

0

Thế còn

ls {*.py,*.html}

Nó liệt kê tất cả các tệp kết thúc bằng .py hoặc .html trong tên tệp của chúng

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.