Tôi muốn tìm các tệp PDF có tên (không bao gồm phần mở rộng) lớn hơn ba.
$ find ~ -iregex ".{3,}/.pdf"
không trả lại gì, nhưng
$ find ~ -iregex ".+/.pdf"
làm.
Làm thế nào tôi có thể kích hoạt các {3,}
biến thể?
Tôi muốn tìm các tệp PDF có tên (không bao gồm phần mở rộng) lớn hơn ba.
$ find ~ -iregex ".{3,}/.pdf"
không trả lại gì, nhưng
$ find ~ -iregex ".+/.pdf"
làm.
Làm thế nào tôi có thể kích hoạt các {3,}
biến thể?
Câu trả lời:
Giả sử bạn đang sử dụng GNU find
(mà bạn có thể là, vì -iregex
là phần mở rộng GNU cho POSIXfind
) -regex
và -iregex
mặc định là biểu thức chính quy của Emacs, không nhận ra {3,}
. Bạn cần chỉ định một loại biểu thức chính quy khác bằng cách sử dụng -regextype
tùy chọn; Ngoài ra, bạn cần điều chỉnh biểu thức chính quy của mình với thực tế là biểu thức khớp với đường dẫn đầy đủ:
find ~ -regextype posix-extended -iregex '.*/[^/]{3,}.pdf'
Bạn cũng nên thoát ra .
để nó khớp với. thay vì bất kỳ nhân vật nào:
find ~ -regextype posix-extended -iregex '.*/[^/]{3,}\.pdf'
Biểu thức chính quy có thể được đơn giản hóa vì chúng ta chỉ quan tâm đến ba ký tự không phải là -
find ~ -regextype posix-extended -iregex '.*[^/]{3}\.pdf'
Để hoàn thiện, với FreeBSD hoặc NetBSD find
(một triển khai khác hỗ trợ -iregex
, không phải của bạn mặc dù .+
sẽ không hoạt động ở đó mà không có -E
), bạn sẽ viết:
find ~ -iregex '.*[^/]\{3\}\.pdf'
hoặc là:
find -E ~ -iregex '.*[^/]{3}\.pdf'
Không có -E
, đó là biểu thức chính quy cơ bản (như trong grep
) và với -E
biểu thức chính quy mở rộng (như trong grep -E
).
Với ast-open's find
:
find ~ -iregex '.*[^/]{3}\.pdf'
(đó là regexps mở rộng ra khỏi hộp).
Ở đây dễ dàng hơn với các ký tự đại diện tiêu chuẩn:
find ~ -name '*???.[pP][dD][fF]'
Hoặc với một số find
triển khai (những hỗ trợ -regex
cũng hỗ trợ -iname
):
find ~ -iname '*???.pdf'
Đối với số lượng ký tự tùy ý thay vì 3
, đó là nơi bạn có thể muốn hoàn nguyên về -iregex
nơi có sẵn (xem câu trả lời của @Stephen Kitt ) hoặc bạn có thể sử dụng zsh
hoặc đánh bóng ksh93
:
zsh
:
set -o extendedglob # best in ~/.zshrc
printf '%s\n' ~/**/?(#c3,).(#i)pdf(D)
( (D)
để xem xét các tệp và tệp ẩn trong các thư mục ẩn như với find
)
(#cx,y)
là zsh
ký tự đại diện tương đương với biểu thức chính{x,y}
(#i)
cho trường hợp không nhạy cảm?
ký tự đại diện chuẩn cho bất kỳ ký tự đơn nào (như regrec .
)**/
: bất kỳ cấp thư mục con nào (bao gồm 0)ksh93
:
FIGNORE='@(.|..)' # to consider hidden files
set -o globstar
printf '%s\n' **/{3,}(?).~(i:pdf)
@(x|y)
: toán tử ký tự đại diện ksh mở rộng tương tự regrec (x|y)
.FIGNORE
: biến đặc biệt kiểm soát những tập tin bị bỏ qua bởi các khối. Khi được đặt, việc bỏ qua các tệp ẩn thông thường sẽ không được thực hiện, nhưng chúng tôi vẫn muốn bỏ qua các mục .
và ..
thư mục hiện diện.{x,y}(z)
là ksh93
tương đương với regrec z{x,y}
.~(i:...)
: khớp không phân biệt chữ hoa chữ thường.Globs có một số lợi thế khác find
ở đây khi bạn có được một danh sách được sắp xếp (bạn có thể vô hiệu hóa việc sắp xếp đó zsh
với oN
vòng loại toàn cầu hoặc sử dụng các tiêu chí sắp xếp khác nhau) và cũng hoạt động khi tên tệp chứa chuỗi byte không tạo thành các ký tự hợp lệ (cho chẳng hạn, trong một ngôn ngữ sử dụng bộ ký tự UTF-8, find
cách tiếp cận sẽ không báo cáo $'St\xE9phane Chazelas - CV.pdf
vì \xE9
không phải là ký tự không khớp với biểu thức chính quy .
hoặc ký tự đại diện ?
hoặc *
với GNU find
).
shopt -s dotglob globstar; printf '%s\n' ~/**/*???.[pP][dD][fF]
Bạn không trừ khi bạn yêu cầu. Chắc chắn, tôi là người phạm tội, nhưng bạn đã không hỏi về các tập tin có .pdf
tên của họ . Chỉ vì một tệp có các ký tự .pdf
trong tên tệp không biến nó thành tệp PDF .
Trên thực tế, chúng ta hãy nói một cách toàn diện về điều này: nếu bốn ký tự cuối cùng của tên tệp là .pdf
, thì nó sẽ luôn có nhiều hơn ba ký tự trong tên của nó .
Vì vậy, làm điều này sai cách , bạn có thể nói:
$ find . -type f -name "*???.pdf"
./Documents/McLaren 720s Coupe:Order Summary.pdf
./Documents/Setup_MagicISO.exe.pdf
Thấy cái thứ hai không? Nó thực sự là một thực thi. (Tôi biết, tôi đã thay đổi tên.) Và tôi cũng đang thiếu một bản PDF mà tôi có thể tuyên thệ có trong thư mục Tài liệu ...
$ ls Documents
McLaren 720s Coupe:Order Summary.pdf
Pioneer Premier DEH-P490IB CD Install Manual.PDF
Setup_MagicISO.exe.pdf
Vì vậy, bằng cách sử dụng -iname
chúng ta có thể tìm thấy cái đó, nhưng nó vẫn xuất hiện tệp không phải là PDF này.
Những gì chúng tôi thực sự muốn làm trong trường hợp này là kiểm tra số ma thuật của tệp bằng cách sử dụng file
lệnh. Một tùy chọn xuất ra loại MIME , đơn giản hơn để phân tích cú pháp. Các find
truy vấn sau đó trở nên đơn giản -name "???*"
.
$ find . -type f -name "???*" -print0|xargs -0 file --mime
./.bash_history: text/plain; charset=us-ascii
./.bash_logout: text/plain; charset=us-ascii
./.bashrc: text/plain; charset=us-ascii
./.profile: text/plain; charset=us-ascii
./Documents/McLaren 720s Coupe:Order Summary.pdf: application/pdf; charset=binary
./Documents/Pioneer Premier DEH-P490IB CD Install Manual.PDF: application/pdf; charset=binary
./Documents/Setup_MagicISO.exe.pdf: application/x-dosexec; charset=binary
./Downloads/Setup_MagicISO.exe: application/x-dosexec; charset=binary
./Downloads/WindowsUpdate.diagcab: application/vnd.ms-cab-compressed; charset=binary
Chúng ta hãy sử dụng dấu phân cách dấu hai chấm và tìm loại MIME application/pdf
, sau đó bỏ phần đó ra và in kết quả. Hãy lưu ý, một trong các tệp của tôi có dấu hai chấm trong tên; vì vậy tôi không thể hỏi awk ($2==":"){print $1}
.
$ find . -type f -name "???*" -print0|xargs -0 file --mime|awk -F: '($NF~"application/pdf"){OFS=":";$NF="";print}'|sed s/:$//
./Documents/McLaren 720s Coupe:Order Summary.pdf
./Documents/Pioneer Premier DEH-P490IB CD Install Manual.PDF
Bây giờ hãy kết thúc bằng cách bao gồm các tệp PDF có tên a
và abc
:
$ mkdir Documents/other
$ cp -a Documents/McLaren\ 720s\ Coupe\:Order\ Summary.pdf Documents/other/a
$ cp -a Documents/Pioneer\ Premier\ DEH-P490IB\ CD\ Install\ Manual.PDF Documents/other/abc
$ find . -type f -name "???*" -print0|xargs -0 file --mime|awk -F: '($NF~"application/pdf"){OFS=":";$NF="";print}'|sed s/:$//
./Documents/McLaren 720s Coupe:Order Summary.pdf
./Documents/Pioneer Premier DEH-P490IB CD Install Manual.PDF
./Documents/other/abc
Đó là tất cả. Tôi biết có lẽ tôi sẽ bị dìm hàng vì bị phạm tội khủng khiếp, nhưng trong công việc của tôi với hàng ngàn khối lượng NFS để săn lùng và tất cả các loại tệp có tên kém, tôi ước nhiều người sẽ là người phạm tội.
Đã chỉnh sửa để thêm: trong thế giới thực, tôi có thể muốn sử dụng updatedb
để xây dựng một chỉ mục tệp có thể tìm kiếm, locate
thay vì find
đọc chỉ mục đó và parallel
thay vì xargs
xâu chuỗi. Điều đó hơi ngoài phạm vi của câu hỏi này mặc dù. Tôi đã viết điều đó với một khuôn mặt thẳng, quá. Tại sao tôi quan tâm nhiều đến vậy? Tôi có thể đang tìm kiếm các tập tin phim và âm thanh; hoặc một số loại hình ảnh; hoặc thực thi nhị phân trong một thư mục dữ liệu dự án.
.pdf
, thì phương pháp sư phạm của bạn sẽ được đánh giá cao. Nhưng đó là một tình huống tương đối bất thường (mặc dù công việc của bạn) và chúng tôi không có bất kỳ lý do nào để tin rằng người hỏi thực sự phải giải quyết vấn đề đó, vì vậy tôi nghĩ rằng quan điểm mà bạn đưa ra, trong khi hợp lệ, là một sự phân tâm - và tôi nghĩ rằng cách mạnh mẽ mà bạn đã thực hiện, nó đẩy câu trả lời vào vương quốc của "(có lẽ) không hữu ích". (Tất nhiên chỉ là ý kiến của tôi.)