Catatan:
* Jawaban ini mungkin lebih dalam dari waran yang digunakan, dan find 2>/dev/null
mungkin 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 find
panggilan 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 shellbash
zsh
Anda atau , ada solusi yang kuat namun cukup sederhana , hanyafind
menggunakan fitur yang sesuai dengan POSIX ; sementara bash
itu 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 grep
output mungkin tiba setelah find
selesai, karena perintah keseluruhan tidak menunggu perintah di dalam >(...)
selesai. Di bash
, Anda dapat mencegah ini dengan menambahkan | cat
perintah.
>(...)
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>
>(...)
bash
zsh
ksh
2> >(...)
ksh 93u+
grep -v 'Permission denied'
menyaring keluar ( -v
) semua lini (dari find
aliran stderr perintah ini) yang mengandung frase Permission denied
dan output garis tersisa untuk stderr ( >&2
).
Pendekatan ini adalah:
robust : grep
hanya 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 find
keluaran 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>&1
harus datang pertama .
Menangkap output stdout dalam file di depan memungkinkan 2>&1
untuk hanya mengirim pesan kesalahan melalui pipa, yang grep
kemudian dapat beroperasi secara jelas.
Satu- satunya downside adalah bahwa kode keluar keseluruhan akan menjadi grep
perintah , 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, find
kode 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: 1
jika demikian, 0
sebaliknya.
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 find
kode 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 3
digunakan untuk bertukar sementara stdout ( 1
) dan stderr ( 2
), sehingga pesan kesalahan saja dapat disalurkan ke grep
via stdout.
Tanpa pengalihan ini, data (jalur file) dan pesan kesalahan akan disalurkan grep
melalui stdout, dan grep
kemudian 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 denied
kesalahan mungkin masih muncul: find ! -readable -prune
melaporkan kesalahan semacam itu untuk item anak - anak dari direktori di mana pengguna saat ini memiliki r
izin, tetapi tidak memiliki izin x
(dapat dieksekusi). Alasannya adalah karena direktori itu sendiri dapat dibaca, -prune
tidak dieksekusi, dan upaya untuk turun ke direktori itu kemudian memicu pesan kesalahan. Yang mengatakan, kasus khas adalah r
izin 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 find
perintah, 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
-name
filter, sebagai berikut:
find . ! -readable -prune -o -name '*.txt'
Akan tetapi, ini tidak berfungsi seperti yang dimaksudkan, karena -print
tindakan 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_file
menanggung 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.
find . 2>&1 > files_and_folders | grep -v 'Permission denied' >&2
?