Saya ingin mencari file PDF yang namanya (tidak termasuk ekstensi) lebih besar dari tiga.
$ find ~ -iregex ".{3,}/.pdf"
mengembalikan apa-apa, tetapi
$ find ~ -iregex ".+/.pdf"
bekerja.
Bagaimana saya bisa mengaktifkan {3,}
varian?
Saya ingin mencari file PDF yang namanya (tidak termasuk ekstensi) lebih besar dari tiga.
$ find ~ -iregex ".{3,}/.pdf"
mengembalikan apa-apa, tetapi
$ find ~ -iregex ".+/.pdf"
bekerja.
Bagaimana saya bisa mengaktifkan {3,}
varian?
Jawaban:
Dengan anggapan Anda menggunakan GNU find
(yang kemungkinan besar adalah Anda, karena -iregex
merupakan ekstensi GNU ke POSIXfind
), -regex
dan -iregex
default untuk ekspresi reguler Emacs, yang tidak dikenali {3,}
. Anda perlu menentukan jenis ekspresi reguler yang berbeda menggunakan -regextype
opsi; selain itu, Anda perlu menyesuaikan ekspresi reguler Anda dengan fakta bahwa ekspresi cocok dengan path lengkap:
find ~ -regextype posix-extended -iregex '.*/[^/]{3,}.pdf'
Anda juga harus melarikan diri .
sehingga cocok dengan “.” daripada karakter apa pun:
find ~ -regextype posix-extended -iregex '.*/[^/]{3,}\.pdf'
Ekspresi reguler dapat disederhanakan karena kami hanya peduli pada tiga karakter non-“/”:
find ~ -regextype posix-extended -iregex '.*[^/]{3}\.pdf'
Untuk kelengkapan, dengan FreeBSD atau NetBSD find
(implementasi lain yang mendukung -iregex
, bukan milik Anda meskipun .+
tidak akan bekerja di sana tanpanya -E
), Anda akan menulis:
find ~ -iregex '.*[^/]\{3\}\.pdf'
atau:
find -E ~ -iregex '.*[^/]{3}\.pdf'
Tanpa -E
, itulah ekspresi reguler dasar (seperti dalam grep
) dan dengan -E
ekspresi reguler yang diperluas (seperti dalam grep -E
).
Dengan ast-open find
:
find ~ -iregex '.*[^/]{3}\.pdf'
(Itu diperpanjang regexps di luar kotak).
Ini lebih mudah dengan wildcard standar:
find ~ -name '*???.[pP][dD][fF]'
Atau dengan beberapa find
implementasi (yang mendukung -regex
juga mendukung -iname
):
find ~ -iname '*???.pdf'
Untuk jumlah karakter yang sewenang-wenang alih-alih 3
, di situlah Anda dapat memilih untuk kembali ke -iregex
tempat yang tersedia (lihat jawaban @Stephen Kitt ) atau Anda dapat menggunakan zsh
atau ksh93
menggila:
zsh
:
set -o extendedglob # best in ~/.zshrc
printf '%s\n' ~/**/?(#c3,).(#i)pdf(D)
( (D)
untuk mempertimbangkan file tersembunyi dan file dalam dirs seperti suka dengan find
)
(#cx,y)
adalah zsh
ekuivalen wildcard dari regexp{x,y}
(#i)
untuk case sensitive?
wildcard standar untuk setiap karakter tunggal (seperti regexp .
)**/
: setiap tingkat subdirektori (termasuk 0)ksh93
:
FIGNORE='@(.|..)' # to consider hidden files
set -o globstar
printf '%s\n' **/{3,}(?).~(i:pdf)
@(x|y)
: operator wildcard extended ksh mirip dengan regexp (x|y)
.FIGNORE
: variabel khusus yang mengontrol file apa yang diabaikan oleh gumpalan. Saat disetel, pengabaian file tersembunyi yang biasa tidak dilakukan, tetapi kami masih ingin mengabaikan entri direktori .
dan ..
jika ada.{x,y}(z)
adalah ksh93
's setara dengan regexp z{x,y}
.~(i:...)
: pencocokan case-insensitive.Gumpalan memiliki beberapa keuntungan tambahan di find
sini karena Anda mendapatkan daftar yang diurutkan (Anda dapat menonaktifkan penyortiran itu zsh
dengan oN
kualifikasi glob, atau menggunakan kriteria penyortiran yang berbeda) dan juga berfungsi ketika nama file berisi urutan byte yang tidak membentuk karakter yang valid (untuk Misalnya, di lokal menggunakan charset UTF-8, find
pendekatan tersebut akan gagal untuk melaporkan a $'St\xE9phane Chazelas - CV.pdf
karena \xE9
karakter yang tidak cocok dengan regexp .
atau wildcard ?
atau *
dengan GNU find
).
shopt -s dotglob globstar; printf '%s\n' ~/**/*???.[pP][dD][fF]
Anda tidak melakukannya kecuali jika Anda bertanya. Tentu, saya menjadi orang yang sangat bertele-tele, tetapi Anda tidak bertanya tentang file dengan .pdf
nama mereka . Hanya karena file memiliki karakter .pdf
dalam nama file tidak menjadikannya file PDF .
Bahkan, mari kita menjadi serba bisa tentang ini: jika empat karakter terakhir dari nama file .pdf
, maka akan selalu memiliki lebih dari tiga karakter dalam namanya .
Jadi melakukan ini dengan cara yang salah , Anda mungkin berkata:
$ find . -type f -name "*???.pdf"
./Documents/McLaren 720s Coupe:Order Summary.pdf
./Documents/Setup_MagicISO.exe.pdf
Lihat yang kedua? Ini sebenarnya sebuah executable. (Saya tahu, saya mengganti namanya.) Dan saya juga kehilangan PDF yang saya sumpah ada di direktori Documents ...
$ ls Documents
McLaren 720s Coupe:Order Summary.pdf
Pioneer Premier DEH-P490IB CD Install Manual.PDF
Setup_MagicISO.exe.pdf
Jadi dengan menggunakan -iname
kita bisa menemukan yang itu, tapi itu masih mengaktifkan file bukan-PDF ini.
Apa yang benar - benar ingin kita lakukan dalam hal ini adalah memeriksa angka ajaib file menggunakan file
perintah. Satu opsi menampilkan tipe MIME , yang lebih mudah diurai. The find
permintaan kemudian menjadi sederhana -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
Mari kita gunakan pembatas titik dua, dan cari tipe MIME application/pdf
, lalu nolkan bagian itu dan cetak hasilnya. Perhatikan, salah satu file saya memiliki titik dua di namanya; jadi saya tidak bisa hanya meminta 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
Sekarang mari kita selesaikan dengan contriving untuk menyertakan file PDF bernama a
dan 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
Itu saja. Saya tahu saya mungkin akan mendapatkan dahsyat karena menjadi pedantic yang mengerikan, tetapi dalam pekerjaan saya dengan ribuan volume NFS untuk diburu dan semua jenis file dengan nama buruk, saya berharap lebih banyak orang menjadi pedantic.
Diedit untuk menambahkan: di dunia nyata, saya mungkin ingin memanfaatkan updatedb
untuk membangun indeks file yang dapat dicari, locate
alih-alih find
membaca indeks itu, dan parallel
alih-alih xargs
utas. Itu agak di luar ruang lingkup pertanyaan ini. Saya menulis itu dengan wajah lurus juga. Mengapa saya sangat peduli? Saya mungkin mencari file film dan audio; atau jenis foto tertentu; atau binary executable dalam direktori data proyek.
.pdf
, maka keriaan Anda akan sangat dihargai. Tapi ini adalah situasi yang relatif tidak biasa (meskipun pekerjaan Anda) dan kami tidak memiliki alasan untuk percaya bahwa penanya sebenarnya harus menghadapinya, jadi saya pikir poin yang Anda buat, meskipun valid, agak mengganggu - dan saya pikir cara kuat Anda telah mengungkapkannya mendorong jawaban ke ranah "(mungkin) tidak berguna". (Pendapat saya saja, tentu saja.)