Bagaimana saya bisa mengecualikan semua pesan "izin ditolak" dari "temukan"?

794

Saya perlu menyembunyikan semua izin pesan yang ditolak dari:

find . > files_and_folders

Saya bereksperimen ketika pesan seperti itu muncul. Saya perlu mengumpulkan semua folder dan file, yang tidak muncul.

Apakah mungkin mengarahkan level izin ke files_and_foldersfile?

Bagaimana saya bisa menyembunyikan kesalahan sekaligus?

Léo Léopold Hertz 준영
sumber

Jawaban:

259

Catatan:
* Jawaban ini mungkin lebih dalam dari waran yang digunakan, dan find 2>/dev/nullmungkin cukup baik dalam banyak situasi. Mungkin masih menarik untuk perspektif lintas-platform dan untuk diskusi tentang beberapa teknik shell canggih demi menemukan solusi yang sekuat mungkin, meskipun kasus-kasus yang dijaga terhadapnya mungkin sebagian besar hipotetis.
* Jika sistem Anda dikonfigurasikan untuk menampilkan pesan kesalahan lokal , awali findpanggilan di bawah ini dengan LC_ALL=C( LC_ALL=C find ...) untuk memastikan bahwa pesan bahasa Inggris dilaporkan, sehingga grep -v 'Permission denied'berfungsi sebagaimana dimaksud. Selalu, bagaimanapun, pesan kesalahan yang tidak bisa ditampilkan kemudian dalam bahasa Inggris juga.

Jika shellbashzsh Anda atau , ada solusi yang kuat namun cukup sederhana , hanyafind menggunakan fitur yang sesuai dengan POSIX ; sementara bashitu sendiri bukan bagian dari POSIX, sebagian besar platform Unix modern datang bersamanya, membuat solusi ini sangat portabel:

find . > files_and_folders 2> >(grep -v 'Permission denied' >&2)

Catatan: Ada kemungkinan kecil bahwa beberapa grepoutput mungkin tiba setelah find selesai, karena perintah keseluruhan tidak menunggu perintah di dalam >(...)selesai. Di bash, Anda dapat mencegah ini dengan menambahkan | catperintah.

  • >(...)adalah substitusi proses output (jarang digunakan) yang memungkinkan redirect output (dalam hal ini, stderr output ( ) ke stdin dari perintah di dalam . Selain dan , mendukung mereka pada prinsipnya , tetapi mencoba menggabungkannya dengan redirection dari stderr , seperti yang dilakukan di sini ( ), tampaknya diabaikan (dalam ) secara diam-diam .2>>(...)
    bashzshksh2> >(...)ksh 93u+

    • grep -v 'Permission denied'menyaring keluar ( -v) semua lini (dari findaliran stderr perintah ini) yang mengandung frase Permission denieddan output garis tersisa untuk stderr ( >&2).

Pendekatan ini adalah:

  • robust : grephanya diterapkan pada pesan kesalahan (dan tidak ke kombinasi jalur file dan pesan kesalahan, berpotensi mengarah ke positif palsu), dan pesan kesalahan selain yang ditolak izin dilewatkan, ke stderr.

  • efek samping bebas : find's kode keluar yang diawetkan: ketidakmampuan untuk mengakses setidaknya salah satu item filesystem ditemui hasil dalam kode keluar 1(meskipun yang tidak akan memberitahu Anda apakah kesalahan lain daripada yang izin-membantah terjadi (juga)).


Solusi yang sesuai dengan POSIX:

Solusi yang sepenuhnya sesuai dengan POSIX memiliki keterbatasan atau membutuhkan pekerjaan tambahan.

Jika findkeluaran adalah untuk ditangkap dalam sebuah berkas pula (atau ditekan sama sekali), maka solusi berbasis pipa dari jawaban Jonathan Leffler sederhana, kuat, dan POSIX-compliant:

find . 2>&1 >files_and_folders | grep -v 'Permission denied' >&2

Perhatikan bahwa urutan hal-hal pengalihan: 2>&1harus datang pertama .

Menangkap output stdout dalam file di depan memungkinkan 2>&1untuk hanya mengirim pesan kesalahan melalui pipa, yang grepkemudian dapat beroperasi secara jelas.

Satu- satunya downside adalah bahwa kode keluar keseluruhan akan menjadi grepperintah , bukan find, yang dalam hal ini berarti: jika tidak ada kesalahan sama sekali atau hanya kesalahan izin ditolak, kode keluar akan menjadi 1( kegagalan pensinyalan ), jika tidak ( kesalahan selain dari izin yang ditolak) 0- yang merupakan kebalikan dari maksud.
Yang mengatakan, findkode keluar jarang digunakan , karena sering menyampaikan sedikit informasi di luar kegagalan mendasar seperti melewati jalur yang tidak ada.
Namun, kasus spesifik bahkan hanya beberapadari jalur masukan yang tidak dapat diakses karena kurangnya hak akses yang tercermin dalam find's kode keluar (di kedua GNU dan BSD find): jika kesalahan izin-membantah terjadi untuk setiap file diproses, kode keluar diatur ke 1.

Variasi berikut membahas bahwa:

find . 2>&1 >files_and_folders | { grep -v 'Permission denied' >&2; [ $? -eq 1 ]; }

Sekarang, kode keluar menunjukkan apakah ada kesalahan selain yang Permission denied terjadi: 1jika demikian, 0sebaliknya.
Dengan kata lain: kode keluar sekarang mencerminkan maksud sebenarnya dari perintah: sukses ( 0) dilaporkan, jika tidak ada kesalahan sama sekali atau hanya kesalahan izin yang ditolak terjadi.
Ini bisa dibilang lebih baik daripada hanya melewati findkode keluar, seperti pada solusi di atas.


gniourf_gniourf dalam komentar mengusulkan generalisasi (masih sesuai-POSIX) dari solusi ini menggunakan pengalihan canggih , yang bekerja bahkan dengan perilaku default mencetak jalur file ke stdout :

{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1

Singkatnya: deskriptor file khusus 3digunakan untuk bertukar sementara stdout ( 1) dan stderr ( 2), sehingga pesan kesalahan saja dapat disalurkan ke grepvia stdout.

Tanpa pengalihan ini, data (jalur file) dan pesan kesalahan akan disalurkan grepmelalui stdout, dan grepkemudian tidak akan dapat membedakan antara pesan kesalahan Permission denied dan file (hipotetis) yang namanya mengandung frase tersebut Permission denied.

Akan tetapi, seperti pada solusi pertama, kode keluar yang dilaporkan adalah grep, bukan find, tetapi perbaikan yang sama seperti di atas dapat diterapkan.


Catatan tentang jawaban yang ada:

  • Ada beberapa poin yang perlu diperhatikan tentang jawaban Michael Brux ini , find . ! -readable -prune -o -print:

    • Itu membutuhkan GNU find ; terutama, itu tidak akan berfungsi pada macOS. Tentu saja, jika Anda hanya perlu perintah untuk bekerja dengan GNU find, ini tidak akan menjadi masalah bagi Anda.

    • Beberapa Permission deniedkesalahan mungkin masih muncul: find ! -readable -prunemelaporkan kesalahan semacam itu untuk item anak - anak dari direktori di mana pengguna saat ini memiliki rizin, tetapi tidak memiliki izin x(dapat dieksekusi). Alasannya adalah karena direktori itu sendiri dapat dibaca, -prunetidak dieksekusi, dan upaya untuk turun ke direktori itu kemudian memicu pesan kesalahan. Yang mengatakan, kasus khas adalah rizin hilang.

    • Catatan: Poin berikut ini adalah masalah filosofi dan / atau kasus penggunaan khusus, dan Anda mungkin memutuskan itu tidak relevan bagi Anda dan bahwa perintah itu sesuai dengan kebutuhan Anda dengan baik, terutama jika hanya mencetak jalur yang Anda lakukan:

      • Jika Anda mengkonseptualkan pemfilteran pesan kesalahan yang ditolak izin sebagai tugas terpisah yang ingin Anda bisa terapkan pada perintah apa pun find , maka pendekatan sebaliknya untuk mencegah kesalahan yang ditolak izin secara proaktif mengharuskan memasukkan "noise" ke dalam findperintah, yang juga memperkenalkan kompleksitas dan perangkap logis .
      • Sebagai contoh, komentar yang paling banyak dipilih pada jawaban Michael (pada tulisan ini) mencoba untuk menunjukkan bagaimana memperluas perintah dengan memasukkan -namefilter, sebagai berikut:
        find . ! -readable -prune -o -name '*.txt'
        Akan tetapi, ini tidak berfungsi seperti yang dimaksudkan, karena -printtindakan trailing diperlukan (penjelasan dapat ditemukan dalam jawaban ini ). Kehalusan seperti itu dapat menyebabkan bug.
  • Solusi pertama di jawaban Jonathan Leffler , find . 2>/dev/null > files_and_folders, karena ia sendiri menyatakan, membabi buta membungkam semua pesan kesalahan (dan solusi yang rumit dan tidak sepenuhnya kuat, karena ia juga menjelaskan). Namun demikian, secara pragmatis , ini adalah solusi paling sederhana , karena Anda mungkin puas mengasumsikan bahwa setiap dan semua kesalahan akan terkait dengan izin.

  • Jawaban kabut ini , sudo find . > files_and_folders, ringkas dan pragmatis, tapi keliru untuk apa saja selain hanya mencetak nama file , untuk alasan keamanan: karena Anda menjalankan sebagai akar pengguna, "Anda berisiko memiliki seluruh sistem Anda menjadi kacau oleh bug di find atau versi jahat, atau doa yang salah yang menulis sesuatu secara tidak terduga, yang tidak dapat terjadi jika Anda menjalankan ini dengan hak istimewa normal "(dari komentar pada jawaban kabut oleh tripleee ).

  • Solusi ke-2 dalam jawaban viraptor , find . 2>&1 | grep -v 'Permission denied' > some_filemenanggung risiko false positive (karena mengirim campuran stdout dan stderr melalui pipa), dan, berpotensi, alih-alih melaporkan kesalahan yang tidak diterima-ditolak melalui stderr, menangkapnya di samping jalur output dalam file output.

mklement0
sumber
4
Hanya pertanyaan singkat: mengapa Anda menggunakan substitusi proses dan bukan hanya pipa: find . 2>&1 > files_and_folders | grep -v 'Permission denied' >&2?
gniourf_gniourf
2
@ LéoLéopoldHertz 준영: Jika Anda tidak ingin meng-output ke file eksternal, cukup lakukan lebih banyak plumbing:{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1
gniourf_gniourf
2
@ LéoLéopoldHertz 준영: Hanya saja itu sesuai dengan POSIX. Proses penggantian >(...)adalah spesifik-Bash.
gniourf_gniourf
2
Saya tidak yakin bahwa pelestarian kode keluar findharus ditekankan dan diiklankan: findkode keluar itu tidak berguna. Di sini, sangat mungkin tidak nol (dan sia-sia).
gniourf_gniourf
3
POSIX secara eksplisit memerlukan execute/searchizin mode file untuk 'mencari' direktori (mengambil inode file yang ada). findmelakukan ini untuk turun ke subdirektori (selain memerlukan readizin untuk mendaftar file dalam direktori). Ini bukan 'bug' atau 'kesalahan porting'.
wjordan
542

Menggunakan:

find . 2>/dev/null > files_and_folders

Permission deniedTentu saja ini tidak hanya menyembunyikan kesalahan, tetapi semua pesan kesalahan.

Jika Anda benar-benar ingin menyimpan kemungkinan kesalahan lain, seperti terlalu banyak hop pada symlink, tetapi bukan izin yang ditolak, maka Anda mungkin harus menebak bahwa Anda tidak memiliki banyak file yang disebut 'izin ditolak' dan coba:

find . 2>&1 | grep -v 'Permission denied' > files_and_folders

Jika Anda benar-benar ingin memfilter hanya kesalahan standar, Anda dapat menggunakan konstruksi yang lebih rumit:

find . 2>&1 > files_and_folders | grep -v 'Permission denied' >&2

I / O redirection pada findperintah: 2>&1 > files_and_folders |. Pipa mengarahkan output standar ke grepperintah dan diterapkan terlebih dahulu. The 2>&1mengirim standard error ke tempat yang sama sebagai output standar (pipa). The > files_and_foldersmengirimkan output standar (tapi kesalahan tidak standar) ke sebuah file. Hasil akhirnya adalah bahwa pesan yang ditulis dengan kesalahan standar dikirim ke pipa dan output reguler findditulis ke file. The grepmenyaring output standar (Anda dapat memutuskan bagaimana selektif Anda inginkan, dan mungkin harus mengubah ejaan tergantung pada lokal dan O / S) dan final>&2berarti pesan kesalahan yang bertahan (ditulis ke output standar) sekali lagi ke kesalahan standar. Pengalihan akhir dapat dianggap sebagai opsional di terminal, tetapi akan menjadi ide yang sangat bagus untuk menggunakannya dalam skrip sehingga pesan kesalahan muncul pada kesalahan standar.

Ada variasi tanpa akhir pada tema ini, tergantung pada apa yang ingin Anda lakukan. Ini akan bekerja pada varian Unix apa pun dengan turunan shell Bourne (Bash, Korn, ...) dan semua versi yang sesuai dengan POSIX find.

Jika Anda ingin beradaptasi dengan versi spesifik yang findAnda miliki di sistem Anda, mungkin ada opsi alternatif yang tersedia. GNU findkhususnya memiliki banyak sekali opsi yang tidak tersedia di versi lain - lihat jawaban yang saat ini diterima untuk satu set opsi tersebut.

Jonathan Leffler
sumber
9
Jika Anda seperti saya, perhatikan bahwa kurangnya ruang penting! 2>/dev/null, tanpa ruang!
Nik
20
Ini 2>adalah unit tunggal tanpa spasi; Anda dapat memiliki ruang di antara itu dan nama file. Demikian pula dengan pengalihan lainnya, seperti 2>&1(yang mengarahkan kesalahan standar ke tempat yang sama dengan keluaran standar), atau 2>&-yang menutup kesalahan standar, dll. Lihat Pengalihan untuk detail berdarah yang tersisa. (Kode di atas adalah shell mirip POSIX generik, tidak khusus untuk bash.)
Jonathan Leffler
3
Saya harus menggunakan huruf P karena itulah yang akan dihasilkan terminal saya: temukan. 2> & 1 | grep -v 'Izin ditolak'
David Doria
4
Bagaimana ini solusi yang dapat diterima? 1) Anda mengarahkan SEMUA kesalahan ke dev / null 2) Anda memfilter string kesalahan eksplisit !! Tergantung pada ini terkenal rapuh dan bagaimana jika file Anda di direktori bernama 'izin ditolak'? Ups!
Gunchar
10
Saya keberatan grepping string kesalahan untuk memodifikasi output program. Ini akan berfungsi sebagian besar waktu, tetapi sederhana bukan solusi yang benar (temukan dengan perms di bawah ini). Untuk memberi Anda contoh mengapa, ini tidak akan berfungsi di OSX karena kesalahannya adalah "Izin ditolak". Sama untuk sistem lain di mana bahkan ada perbedaan sangat kecil dalam string kesalahan (internasionalisasi siapa pun?)
Gunchars
285

Menggunakan:

find . ! -readable -prune -o -print

atau lebih umum

find <paths> ! -readable -prune -o <other conditions like -name> -print
  • untuk menghindari "Izin ditolak"
  • DAN JANGAN menekan pesan kesalahan (lainnya)
  • DAN dapatkan status keluar 0 ("semua file berhasil diproses")

Bekerja dengan: find (GNU findutils) 4.4.2. Latar Belakang:

  • The -readablelaga uji coba file yang dapat dibaca. The !Operator mengembalikan benar, ketika tes adalah palsu. Dan ! -readablecocok dengan direktori (& file) yang tidak dapat dibaca.
  • The -prunetindakan tidak turun ke direktori.
  • ! -readable -prune dapat diterjemahkan ke: jika direktori tidak dapat dibaca, jangan turun ke dalamnya.
  • The -readableuji memperhitungkan daftar kontrol akses dan artefak izin lainnya yang -permabaikan tes.

Lihat juga find(1) manual untuk lebih banyak detail.

Michael Brux
sumber
6
perbedaan sudah disebutkan. jika Anda tidak mengerti, maka jawabannya mungkin tidak membuat perbedaan bagi Anda? STDOUT sama - STDERR berbeda (Anda mendapatkan pesan kesalahan lainnya dengan jawaban ini) - $? berbeda (apakah 0 "berhasil" dengan jawaban ini, ketika tidak ada kesalahan lain terjadi - selalu> 0 "tidak berhasil" ketika mengarahkan ulang ke dev / null) - mungkin seseorang membutuhkan "benar" $? dalam naskah
Michael Brux
6
@Masi cacat yang paling jelas adalah jawaban Jonathan (grep -v) akan mengecualikan nama file yang berisi 'Izin ditolak' :)
Buah
65
Saya merasa pantas untuk menambahkan di sini bahwa jika Anda perlu menambahkan beberapa kriteria pencarian lain, itu harus dilakukan dengan -o:find . ! -readable -prune -o -name '*.txt'
tempestadept
22
Perhatikan bahwa POSIX findtidak termasuk -readablesebagai opsi; begitu juga finduntuk BSD dan karenanya Mac OS X (saya tidak yakin tentang sistem lain). Jadi, di mana Anda finddijamin GNU , ini berfungsi dengan baik, tetapi tidak jelas bagaimana mengadaptasi ini jika Anda tidak dapat menjamin bahwa sistem telah findmenginstal GNU . (Ini akan bekerja dengan baik di Linux; itu mungkin atau mungkin tidak bekerja di tempat lain.)
Jonathan Leffler
6
find . ! -readable -prune -o -name '*.txt'tampaknya tidak berfungsi di Ubuntu 14.04 menggunakan find 4.2.2. Tampaknya untuk menelan -name. Untuk beberapa alasan aneh saya sukses denganfind . \( ! -readable -prune \) -o -name '*.txt' -print
gunakan con
110

Jika Anda ingin memulai pencarian dari root "/", Anda mungkin akan melihat output seperti:

find: /./proc/1731/fdinfo: Permission denied
find: /./proc/2032/task/2032/fd: Permission denied

Itu karena izin. Untuk mengatasi ini:

  1. Anda dapat menggunakan perintah sudo:

    sudo find /. -name 'toBeSearched.file'

Ia meminta kata sandi pengguna super, ketika memasukkan kata sandi Anda akan melihat hasil apa yang Anda inginkan. Jika Anda tidak memiliki izin untuk menggunakan perintah sudo yang berarti Anda tidak memiliki kata sandi pengguna super, pertama-tama minta admin sistem untuk menambahkan Anda ke file sudoers.

  1. Anda dapat menggunakan redirect Output Kesalahan Standar dari (Umumnya Tampilan / Layar) ke beberapa file dan menghindari melihat pesan kesalahan di layar! redirect ke file khusus / dev / null:

    find /. -name 'toBeSearched.file' 2>/dev/null
  2. Anda dapat menggunakan redirect Output Kesalahan Standar dari (Umumnya Tampilan / Layar) ke Output standar (Umumnya Tampilan / Layar), kemudian pipa dengan perintah grep dengan -v "invert" parameter untuk tidak melihat garis output yang memiliki 'Izin ditolak' pasangan kata:

    find /. -name 'toBeSearched.file' 2>&1 | grep -v 'Permission denied'
Fatih Aksu
sumber
7
@ skottmrogowski kecuali itu tidak menjawab pertanyaan ... 1. minta admin sistem untuk menambahkan Anda ke file sudoers. 2.sudo find...
Stephen
1
persis apa yang saya cari!
DankMasterDan
92

Saya harus menggunakan:

find / -name expect 2>/dev/null

menentukan nama apa yang ingin saya temukan dan kemudian mengatakannya untuk mengalihkan semua kesalahan ke / dev / null

berharap menjadi lokasi program ekspektasi yang saya cari.

Jeremy
sumber
3
@Masi, perintah dalam jawaban tidak digunakan expect. Sebaliknya, expecthanya nama file yang akan dicari perintah ini.
Dhruv Kapoor
2
Mengarahkan semua output stderr hanya untuk mengabaikan satu kelas pesan kesalahan umumnya merupakan ide yang buruk - Anda akan kehilangan semua kesalahan sewenang-wenang lainnya dalam proses.
Josip Rodin
59

Pipa stderrke /dev/nulldengan menggunakan 2> / dev / null

find . -name '...' 2>/dev/null

Mat
sumber
2
Ini berfungsi dengan baik untuk saya bahkan di Mac OSX. Atau bahkanfind . -name '...' -print 2>/dev/null
shadowsheep
30

Anda juga dapat menggunakan -permdan -prunepredikat untuk menghindari turun ke direktori yang tidak dapat dibaca (lihat juga Bagaimana cara menghapus pernyataan cetakan "izin ditolak" dari program find? - Unix & Linux Stack Exchange ):

find . -type d ! -perm -g+r,u+r,o+r -prune -o -print > files_and_folders
sdaau
sumber
4
-perm -g+r,u+r,o+rhanya cocok dengan file yang memiliki rizin (baca) yang ditetapkan untuk ketiga prinsip keamanan file , yang tidak memiliki hubungan langsung dengan apakah pengguna saat ini dapat membaca file itu atau tidak. Ini memiliki potensi untuk kehilangan file yang pengguna saat ini dapat membaca dan untuk mencocokkan file yang mereka tidak bisa.
mklement0
Saya pikir find . -type d ! \( -perm -u+r -o -perm -g+r -o -perm -o+r \) -prune -o -printakan menjadi solusi yang baik.
Mattia72
2
@ Mattia72: Tidak, pada dasarnya tidak mungkin untuk sepenuhnya ditiru -readabledengan -perm- lihat komentar saya sebelumnya dan pertimbangkan contoh ini: echo 'hi' > file; sudo chown nobody:nobody file; sudo chmod o-r file; find file -perm -u=rmencetak file, karena bit baca penggunanya diatur, tetapi ini berhubungan dengan nobodypengguna, bukan pengguna saat ini. Pengguna saat ini tidak dapat membaca file ini; coba cat file. Lihat juga: jawaban saya ini.
mklement0
23

Arahkan ulang kesalahan standar. Misalnya, jika Anda menggunakan bash pada mesin unix, Anda dapat mengarahkan kesalahan standar ke / dev / null seperti ini:

find . 2>/dev/null >files_and_folders
Jason Coco
sumber
20

Meskipun pendekatan di atas tidak membahas kasus untuk Mac OS X karena Mac Os X tidak mendukung -readablesakelar, ini adalah cara Anda dapat menghindari kesalahan 'Izin ditolak' di output Anda. Ini mungkin membantu seseorang.

find / -type f -name "your_pattern" 2>/dev/null.

Jika Anda menggunakan perintah lain dengan find, misalnya, untuk menemukan ukuran file dari pola tertentu dalam direktori 2>/dev/nullmasih akan berfungsi seperti yang ditunjukkan di bawah ini.

find . -type f -name "your_pattern" -exec du -ch {} + 2>/dev/null | grep total$.

Ini akan mengembalikan ukuran total file dari pola yang diberikan. Catat 2>/dev/nullpada akhir perintah find.

Bunti
sumber
Bagus mengikat OS X! Jawaban Jonathan menjelaskan bagian itu 2>/dev/null. Bisakah Anda jelaskan bagiannya -exec du -ch {} + 2>/dev/null | grep total$.
Léo Léopold Hertz 준영
1
@Masi Anda dapat menggunakan perintah apa saja dengan -execopsi untuk mengambil tindakan lebih lanjut pada file atau direktori yang ditemukan oleh findperintah. du -ch file_patternmenghitung ukuran setiap pencocokan file file_patterndan baris terakhir dari output itu adalah total keseluruhan dari semua file yang cocok dengan file_pattern. Lihat halaman manual untuk du. grep totalcukup filter baris yang mengekstrak total keseluruhan (yang merupakan baris terakhir).
Bunti
13

Kesalahan itu dicetak ke output kesalahan standar (fd 2). Untuk memfilternya, cukup arahkan semua kesalahan ke / dev / null:

find . 2>/dev/null > some_file

atau pertama bergabung dengan stderr dan stdout dan kemudian singkirkan kesalahan spesifik tersebut:

find . 2>&1 | grep -v 'Permission denied' > some_file
viraptor
sumber
11

Jawaban sederhana:

find . > files_and_folders 2>&-

2>&-menutup ( -) deskriptor file kesalahan standar ( 2) sehingga semua pesan kesalahan dibungkam.

  • Kode keluar akan tetap ada 1jika ada Permission deniedkesalahan ' ' jika tidak akan dicetak

Jawaban yang kuat untuk GNU find:

find . -type d \! \( -readable -executable \) -prune -print -o -print > files_and_folders

Berikan opsi tambahan untuk finditu -prune(mencegah turun ke) tetapi masih -printada direktori ( ) yang tidak ( ) memiliki keduanya dan izin, atau ( ) file lain.-typed\!-readable-executable-o-print

  • -readabledan -executableopsi adalah ekstensi GNU, bukan bagian dari standar POSIX
  • Mungkin masih mengembalikan ' Permission denied' pada file yang tidak normal / rusak (mis., Lihat laporan bug yang memengaruhi sistem file yang dipasang di wadah menggunakan lxcfs<v2.0.5)

Jawaban kuat yang bekerja dengan semua yang kompatibel dengan POSIX find(GNU, OSX / BSD, dll)

{ LC_ALL=C find . 3>&2 2>&1 1>&3 > files_and_folders | grep -v 'Permission denied'; [ $? = 1 ]; } 3>&2 2>&1

Gunakan pipa untuk melewatkan aliran kesalahan standar grep, menghapus semua baris yang mengandung 'Permission denied'string.

LC_ALL=Cmengatur lokal POSIX menggunakan variabel lingkungan , 3>&2 2>&1 1>&3dan 3>&2 2>&1 menduplikasi deskriptor file untuk menyalurkan aliran kesalahan standar grep, dan [ $? = 1 ]menggunakan []untuk membalikkan kode kesalahan yang dikembalikan oleh grepuntuk memperkirakan perilaku asli find.

  • Juga akan memfilter 'Permission denied'kesalahan apa pun karena pengalihan output (mis., Jika files_and_foldersfile itu sendiri tidak dapat ditulisi)
wjordan
sumber
Bagaimana pendapat Anda tentang proposal jawaban JordiFerran? - - Bisakah Anda membandingkan jawaban Anda dengan itu?
Léo Léopold Hertz 준영
2
Skrip shell jawaban seperti yang dinyatakan bukan untuk tujuan umum (hanya daftar direktori yang cocok dengan $ {m_find_name}), dan berisi beberapa opsi yang tidak relevan dengan pertanyaan (nice, / home *, -maxdepth 5, -follow). Jawaban ini membahas masalah spesifik 'pemfilteran direktori yang dapat dibaca tetapi tidak dapat dieksekusi' secara lebih ringkas, namun tetap bertujuan umum.
wjordan
1
@wjordan: Terima kasih. Aku telah menghapus komentar saya, tapi satu titik masih berlaku: yang -permsolusi berbasis tidak layak presentasi, karena lebih mendasar daripada kutipan menyarankan melakukan sesuatu yang berbeda daripada yang dimaksudkan: itu adalah murni berkas-sentris tes, yang berkaitan dengan file pemilik dan grup, yang keduanya tidak memiliki hubungan yang dijamin dengan pengguna yang memanggil perintah (lihat jawaban saya ini. Sepertinya solusi GNU Anda yang direvisi sekarang tidak menangkap izin yang ditolak kesalahan yang berasal dari file .
mklement0
Saya tidak mengenali sintaks yang Anda gunakan (baik sebagai GNU maupun sebagai BSD), tetapi izinkan saya mengilustrasikan poin saya dengan contoh mandiri: echo 'hi' > file; sudo chown nobody:nobody file; sudo chmod o-r file; find file -perm -u=rcetakan file, karena bit yang dibaca pengguna disetel, tetapi ini berkaitan dengan nobodypengguna , bukan pengguna saat ini. Pengguna saat ini tidak dapat membaca file ini; coba cat file.
mklement0
1
@ mklement0 terima kasih untuk diskusi, saya berhasil menghasilkan perilaku yang Anda uraikan dalam tes lain (tidak tahu apa yang saya lakukan salah pertama kali), sepertinya -permtidak bekerja untuk menentukan izin pengguna saat ini. Menghapus alternatif itu dari jawaban ini.
wjordan
4

Untuk menghindari hanya izin yang ditolak peringatannya, beri tahu find untuk mengabaikan file yang tidak dapat dibaca dengan memangkasnya dari pencarian. Tambahkan ekspresi sebagai ATAU ke penemuan Anda, seperti

find / \! -readable -prune -o -name '*.jbd' -ls

Ini sebagian besar mengatakan untuk (mencocokkan file yang tidak dapat dibaca dan memangkasnya dari daftar) ATAU (cocokkan nama seperti * .jbd dan menampilkannya [dengan ls]) . (Ingatlah bahwa secara default ekspresi adalah AND'd bersama kecuali jika Anda menggunakan -atau) Anda memerlukan -l dalam ekspresi kedua atau jika ditemukan dapat menambahkan tindakan default untuk menunjukkan kecocokan, yang juga akan menunjukkan kepada Anda semua file yang tidak dapat dibaca .

Tetapi jika Anda mencari file nyata di sistem Anda, biasanya tidak ada alasan untuk mencari / dev, yang memiliki banyak file, jadi Anda harus menambahkan ekspresi yang mengecualikan direktori itu, seperti:

find / -mount \! -readable -prune  -o  -path /dev -prune  -o  -name '*.jbd' -ls

Jadi (cocokkan file yang tidak dapat dibaca dan pangkas dari daftar) ATAU (cocokkan jalur / dev dan pangkas dari daftar) ATAU (cocokkan file seperti * .jbd dan tampilkan) .

pengguna sederhana
sumber
4

menggunakan

sudo find / -name file.txt

Ini bodoh (karena Anda meningkatkan pencarian) dan tidak aman, tetapi jauh lebih pendek untuk menulis.

kabut
sumber
Anda mencari di sini seluruh sistem file sehingga Anda maksud dengan ini "meninggikan pencarian". Mengapa Anda menyebutnya tidak aman? Karena mencari seluruh sistem file?
Léo Léopold Hertz 준영
2
Karena sudo menjalankan perintah find dengan izin root yang pada dasarnya adalah ide yang buruk. Prinsip-prinsip segregasi dan privilege-privilege dilanggar.
kabut
3
"Ketinggian" di sini adalah hak istimewa, untuk root, dengan sudo. Anda berisiko seluruh sistem Anda dikacaukan oleh bug di findatau versi jahat, atau doa yang salah yang menulis sesuatu secara tidak terduga, yang tidak dapat terjadi jika Anda menjalankan ini dengan hak-hak istimewa yang normal.
tripleee
2

Tidak ada jawaban di atas yang berfungsi untuk saya. Apa pun yang saya temukan di Internet berfokus pada: sembunyikan kesalahan. Tidak ada yang menangani proses kode-kembali / kode-keluar dengan benar. Saya menggunakan perintah find dalam skrip bash untuk menemukan beberapa direktori dan kemudian memeriksa isinya. Saya mengevaluasi perintah temukan sukses menggunakan kode keluar: nilai nol berfungsi, jika tidak gagal.

The jawaban yang diberikan di atas oleh Michael Brux bekerja kadang-kadang. Tapi saya punya satu skenario di mana ia gagal! Saya menemukan masalah dan memperbaikinya sendiri. Saya perlu memangkas file ketika:

it is a directory AND has no read access AND/OR has no execute access

Lihat masalah utama di sini adalah: DAN / ATAU. Satu urutan kondisi yang disarankan yang saya baca adalah:

-type d ! -readable ! -executable -prune

Ini tidak selalu berhasil. Ini berarti pemangkasan dipicu ketika pertandingan adalah:

it is directory AND no read access AND no execute access

Urutan ekspresi ini gagal ketika akses baca diberikan tetapi tidak ada akses eksekusi.

Setelah beberapa pengujian saya menyadari tentang itu dan mengubah solusi skrip shell saya ke:

nice find / home * / -maxdepth 5 -Ikuti \
    \ (-type d -a ! \ (-baca-a-bisa dieksekusi \) \) -prune \
    -o \
    \ (-jenis d -b -baca -a - executable -a -name "$ {m_find_name}" \) -print

Kuncinya di sini adalah menempatkan "tidak benar" untuk ekspresi gabungan:

has read access AND has execute access

Kalau tidak, ia tidak memiliki akses penuh, yang berarti: memangkasnya. Ini terbukti bekerja untuk saya dalam satu skenario yang gagal solusi yang disarankan sebelumnya.

Saya memberikan rincian teknis di bawah ini untuk pertanyaan di bagian komentar. Saya minta maaf jika detailnya berlebihan.

  • ¿Mengapa menggunakan perintah yang bagus? Saya mendapat ide di sini . Awalnya saya pikir akan menyenangkan untuk mengurangi prioritas proses ketika mencari seluruh sistem file. Saya menyadari itu tidak masuk akal bagi saya, karena skrip saya terbatas pada beberapa direktori. Saya mengurangi -maxdepth menjadi 3.
  • ¿Mengapa mencari di dalam / home * /? Ini tidak relevan untuk utas ini. Saya menginstal semua aplikasi dengan tangan melalui kompilasi kode sumber dengan pengguna yang tidak memiliki hak istimewa (bukan root). Mereka dipasang di "/ rumah". Saya dapat memiliki banyak binari dan versi yang hidup bersama. Saya perlu menemukan semua direktori, memeriksa dan membuat cadangan dengan cara master-slave. Saya dapat memiliki lebih dari satu "/ rumah" (beberapa disk berjalan di dalam server khusus).
  • ¿Kenapa menggunakan -follow? Pengguna dapat membuat tautan simbolis ke direktori. Kegunaannya tergantung, saya perlu mencatat jalur absolut yang ditemukan.
Jordi Ferran
sumber
Terima kasih atas jawaban dan pengamatan Anda! Saya membuka hadiah di sini untuk mempratinjau jawaban Anda dengan lebih baik. Saya pikir ini adalah temuan yang bagus dan tidak menghalangi akses baca dan eksekusi. - - Bisakah Anda jelaskan mengapa Anda menggunakan nicedan find $HOME -maxdepth 5 -follow ...?
Léo Léopold Hertz 준영
2
Script shell seperti yang dinyatakan tidak tujuan umum (hanya daftar direktori pencocokan ${m_find_name}), dan berisi beberapa pilihan tidak relevan dengan pertanyaan ( nice, /home*, -maxdepth 5, -follow). Saya telah menambahkan jawaban yang membahas masalah khusus 'memfilter direktori yang dapat dibaca tetapi tidak dapat dieksekusi' secara lebih ringkas, namun tetap memiliki tujuan umum.
wjordan
2

Anda dapat menggunakan grep -v invert-match

-v, --invert-match        select non-matching lines

seperti ini:

find . > files_and_folders
cat files_and_folders | grep -v "permission denied" > files_and_folders

Haruskah dengan keajaiban

Leonardo Hermoso
sumber
2

- = Untuk MacOS = -

Buat perintah baru menggunakan alias: tambahkan saja baris ~ / .bash_profile:

alias search='find / -name $file 2>/dev/null'

dan di jendela Terminal baru Anda bisa menyebutnya:

$ file=<filename or mask>; search

sebagai contoh:

$ file = dll; Cari

Jan alias uptech
sumber
1

Jika Anda menggunakan CSH atau TCSH, berikut ini solusinya:

( find . > files_and_folders ) >& /dev/null

Jika Anda ingin output ke terminal:

( find . > /dev/tty ) >& /dev/null

Namun, seperti yang dijelaskan oleh FAQ "csh-whynot", Anda sebaiknya tidak menggunakan CSH.

Kayle Sawyer
sumber
Saya ingin membuka semua file txt dan mengecualikan file / direktori tersembunyi, mengabaikan pesan "Izin ditolak" untuk dicetak. Saya menggunakan csh shell. Saya telah menggunakan perintah di bawah ini dan mereka tidak berfungsi. -type f -iname " .txt " -not -path '* / \. '| egrep -v "Izin ditolak" temukan. -type f -iname " .txt " -not -path '* / \. '2> / dev / null Mendapatkan di bawah Kesalahan. find: paths harus mendahului ekspresi: 2 Penggunaan: find [-H] [-L] [-P] [-Olevel] [-D help | tree | search | stat | rates | opt | exec] [path ...] [ekspresi]
yadav