Bagaimana cara mengecualikan / mengabaikan file dan direktori tersembunyi dalam pencarian “menemukan” yang disematkan?

119

Mulai dari (perhatikan wildcard sebelum dan sesudah "beberapa teks")

find . -type f -name '*some text*'

bagaimana kita bisa mengecualikan / mengabaikan semua file dan direktori tersembunyi?

Saya sudah googling terlalu lama , menemukan beberapa -prune dan! (tanda seru) parameter, tetapi tidak ada contoh pas (dan pelit) yang hanya bekerja .

Perpipaan | untuk grepmenjadi pilihan dan saya juga menyambut contoh itu; tetapi terutama saya tertarik pada satu-liner singkat (atau beberapa satu-liner yang berdiri sendiri, menggambarkan berbagai cara untuk mencapai tujuan baris perintah yang sama) hanya menggunakan find.

ps: Temukan file di linux dan kecualikan direktori spesifik yang tampaknya terkait erat, tetapi a) belum diterima dan b) terkait-tetapi-berbeda-dan-berbeda, tetapi c) dapat memberikan inspirasi dan membantu menunjukkan kebingungan!

Sunting

find . \( ! -regex '.*/\..*' \) -type f -name "whatever", bekerja. Regex mencari "apa saja, lalu garis miring, lalu titik, lalu apa saja" (yaitu semua file dan folder tersembunyi termasuk subfoldernya), dan "!" meniadakan regex.

gila tentang natty
sumber
Tidak membantu dengan apa yang Anda tanyakan dalam suntingan Anda tetapi lihat pertanyaan saya dan jawabannya di sini: unix.stackexchange.com/q/69164/15760 dan juga tautan dalam jawaban.

Jawaban:

134

Ini mencetak semua file yang merupakan keturunan dari direktori Anda, melewatkan file dan direktori tersembunyi:

find . -not -path '*/\.*'

Jadi, jika Anda mencari file dengan some textnamanya, dan Anda ingin melewati file dan direktori tersembunyi, jalankan:

find . -not -path '*/\.*' -type f -name '*some text*'

Penjelasan:

The -pathpilihan menjalankan pemeriksaan pola terhadap seluruh string path. *adalah wildcard, /adalah pemisah direktori, \.adalah sebuah titik (harus diloloskan untuk menghindari makna khusus), dan *merupakan wildcard lainnya. -notartinya jangan pilih file yang cocok dengan tes ini.

Saya tidak berpikir itu findcukup pintar untuk menghindari mencari direktori tersembunyi secara rekursif dalam perintah sebelumnya, jadi jika Anda membutuhkan kecepatan, gunakan -prunesaja, seperti ini:

 find . -type d -path '*/\.*' -prune -o -not -name '.*' -type f -name '*some text*' -print
Flimm
sumber
Catat dengan yang terakhir yang Anda butuhkan -printdi akhir! Juga, tidak yakin apakah -name '\.*' would be more efficient instead of -path` (karena path sedang mencari subpath, tetapi ini akan dipangkas)
artfulrobot
Apa arti khusus dari .konteks ini?
frostschutz
@frostschutz Titik setelah findberarti direktori saat ini: findakan melihat semua file dan direktori di bawah direktori saat ini. Argumen sesudahnya pathadalah ekspresi reguler, di mana sebuah titik biasanya berarti "karakter apa saja", untuk menjadikannya sebuah titik literal kita harus menghindarinya dengan backslash. Argumen setelah -name itu bukanlah ekspresi reguler, tetapi memperluas wildcard seperti ?dan *seperti shell.
Flimm
2
@ frostschutz Sebenarnya, kalau dipikir-pikir, saya mungkin salah tentang .memiliki makna khusus.
Flimm
1
@Flimm ya, tidak perlu melarikan diri .. Sejauh yang saya tahu, hanya ini perlu melarikan diri: *, ?, dan [].
thdoan
10

Ini adalah salah satu dari sedikit cara mengecualikan file-file dot yang juga berfungsi dengan benar di BSD, Mac dan Linux:

find "$PWD" -name ".*" -prune -o -print
  • $PWD cetak path lengkap ke direktori saat ini sehingga path tidak dimulai ./
  • -name ".*" -prune cocok dengan semua file atau direktori yang dimulai dengan titik dan kemudian tidak turun
  • -o -printberarti mencetak nama file jika ungkapan sebelumnya tidak cocok dengan apa pun. Menggunakan -printatau -print0menyebabkan semua ekspresi lain tidak dapat mencetak secara default.
Eradman
sumber
Tolong jelaskan / uraikan "rumit rumit"; jawaban yang sudah diberikan dan jawaban Anda tampaknya memberikan bukti yang bertentangan ...?
gila tentang natty
2
"sangat rumit" mungkin berlebihan. Saya menulis ulang jawaban untuk langsung ke pokok permasalahan. Saya pikir jawaban yang saya posting sulit untuk dipahami dan sulit untuk dilihat tanpa membaca halaman manual. Jika Anda hanya menggunakan GNU find maka ada solusi yang lebih mungkin.
eradman
-o ... -printmembantu. Untuk penggunaan saya, sekarang saya miliki find ... '!' -name . -name '.*' -prune -o ... -print, yang lebih nyaman daripada memasukkan $ PWD.
Roger Pate
4
find $DIR -not -path '*/\.*' -type f \( ! -iname ".*" \)

Tidak termasuk semua direktori tersembunyi, dan file tersembunyi di bawah $ DIR

tamu
sumber
Ini jawaban yang sempurna. Secara rekursif menemukan semua file tetapi tidak termasuk item baris untuk direktori dan file tersembunyi. Terima kasih!
KyleFarris
2

The jawaban saya awalnya diumumkan sebagai "edit" ke pertanyaan awal saya di atas:

find . \( ! -regex '.*/\..*' \) -type f -name "whatever", bekerja. Regex mencari "apa saja, lalu garis miring, lalu titik, lalu apa saja" (yaitu semua file dan folder tersembunyi termasuk subfoldernya), dan "!" meniadakan regex.

gila tentang natty
sumber
Serupa, tetapi hanya untuk folder saat ini:find . \( ! -regex './\..*' \) -type f -maxdepth 1 -print
phyatt
2

Anda tidak perlu menggunakannya finduntuk itu. Cukup gunakan globstar di shell-nya sendiri, seperti:

echo **/*foo*

atau:

ls **/*foo*

di mana **/merepresentasikan folder apa pun secara rekursif dan *foo*file apa pun yang memiliki foonamanya.

Secara default menggunakan lsakan mencetak nama file tidak termasuk file dan direktori tersembunyi.

Jika Anda tidak mengaktifkan globbing, lakukan dengan shopt -s globstar.

Catatan: Opsi globbing baru berfungsi di Bash 4, zsh dan shell serupa.


Contoh:

$ mkdir -vp a/b/c/d
mkdir: created directory 'a'
mkdir: created directory 'a/b'
mkdir: created directory 'a/b/c'
mkdir: created directory 'a/b/c/d'
$ touch a/b/c/d/foo a/b/c/d/bar  a/b/c/d/.foo_hidden a/b/c/d/foo_not_hidden
$ echo **/*foo*
a/b/c/d/foo  a/b/c/d/foo_not_hidden
kenorb
sumber
5
Anda tidak perlu lsuntuk itu! echo **/*foo*
Kevin Cox
@kenorb (dan @ kevin-cox). Bisakah Anda menjadi sedikit lebih verbose? Mengapa globstar (= *) berfungsi di sini dan bagaimana? Apa yang dilakukan slash?
gila tentang rapi
@nuttyaboutnatty /berarti folder, memisahkan direktori dari nama file. *pada dasarnya mewakili segalanya.
kenorb
@kenorb ya-tapi: bagaimana one-liner membantu dengan pertanyaan aslinya?
gila tentang rapi
1
@nuttyaboutnatty Klarifikasi dan menambahkan contoh. Ini membantu dengan menemukan file yang mengabaikan yang tersembunyi.
kenorb
1

@ Flimm's jawaban baik, terutama karena mencegah menemukan turun ke direktori tersembunyi . Saya lebih suka penyederhanaan ini:

Umumnya untuk mengecualikan semua jalur tersembunyi (file biasa, direktori, dll):

find <start-point> -path '*/.*' -prune -o <expression> -print

Misalnya, menggunakan direktori kerja Anda sebagai titik awal, dan -name '*some text*'sebagai ekspresi:

find . -path '*/.*' -prune -o -name '*some text*' -print

Berbeda dengan apa yang disarankan @ Flimm, tidak ada file tersembunyi atau direktori tersembunyi adalah kasus sederhana. The -path '*/.*'ekspresi benar untuk setiap jalan (file biasa, direktori, dll) yang memiliki .segera setelah pemisah file Anda, /. Jadi baris ini akan memangkas file dan direktori tersembunyi.

Mengizinkan file tersembunyi sambil mengecualikan direktori tersembunyi adalah kasus yang membutuhkan filter lebih lanjut. Di sinilah Anda akan memasukkan -type ddalam ekspresi sedang dipangkas.

find <start-point> -type d -path '*/.*' -prune -o <expression> -print 

Sebagai contoh:

find . -type d -path '*/.*' -prune -o -name '*some text*' -print

Dalam hal -type d -path '*/.*'ini truehanya untuk direktori, dan hanya direktori yang dipangkas.

De Novo
sumber
0

findmemiliki sakelar logika yang rapi seperti -anddan -notAnda dapat menggunakannya untuk keuntungan Anda untuk menemukan file yang cocok dengan dua aturan seperti:

$ touch non_hidden_file.txt .hidden_file.txt somethings/.another_hidden_file.txt                                                 

$ find . -type f -name '*hidden_file*' -and \( -not -name ".*" \)                            
./non_hidden_file.txt

Seperti yang Anda lihat, findgunakan dua aturan -name '*hidden_file*'dan -and \( -not -name ".*" \)untuk menemukan nama file yang cocok dengan kedua kondisi - nama file dengan hidden_filedi dalamnya tetapi tanpa titik awal. Catat garis miring di depan tanda kurung - mereka digunakan untuk mendefinisikan tanda kurung sebagai findargumen, bukan mendefinisikan subkulit (yang artinya tanda kurung dinyatakan tanpa garis miring)

Sergiy Kolodyazhnyy
sumber
0
$ pwd
/home/victoria

$ find $(pwd) -maxdepth 1 -type f -not -path '*/\.*' | sort
/home/victoria/new
/home/victoria/new1
/home/victoria/new2
/home/victoria/new3
/home/victoria/new3.md
/home/victoria/new.md
/home/victoria/package.json
/home/victoria/Untitled Document 1
/home/victoria/Untitled Document 2

$ find . -maxdepth 1 -type f -not -path '*/\.*' | sed 's/^\.\///g' | sort
new
new1
new2
new3
new3.md
new.md
package.json
Untitled Document 1
Untitled Document 2

Catatan:

  • . : folder saat ini
  • hapus -maxdepth 1untuk mencari secara rekursif
  • -type f: cari file, bukan direktori ( d)
  • -not -path '*/\.*' : jangan kembali .hidden_files
  • sed 's/^\.\///g': hapus yang diawali ./dari daftar hasil
Victoria Stuart
sumber