Примітка:
* Ця відповідь, ймовірно, йде глибше, ніж вимагає випадок використання, і find 2>/dev/null
може бути досить хорошим у багатьох ситуаціях. Це все ще може представляти інтерес для кросплатформенної перспективи та для обговорення деяких передових методів оболонки, щоб знайти рішення, яке є максимально надійним, хоча випадки, щодо яких захищаються, можуть бути значною мірою гіпотетичними.
* Якщо ваша система налаштована на показ локалізованих повідомлень про помилки , приставте find
виклики нижче за допомогою LC_ALL=C
( LC_ALL=C find ...
), щоб переконатися в повідомленні англійських повідомлень, щоб це grep -v 'Permission denied'
працювало за призначенням. Однак незмінно будь-які повідомлення про помилки, які відображаються, також будуть англійською мовою.
Якщо ваша оболонка є bash
абоzsh
є рішення, яке є надійним і при цьому досить просто , використовуючи лише сумісні з POSIX find
функції ; хоча bash
сам по собі не є частиною POSIX, більшість сучасних платформ Unix поставляються з ним, що робить це рішення широко портативним:
find . > files_and_folders 2> >(grep -v 'Permission denied' >&2)
Примітка: Є невеликий шанс, що деякий з grep
результатів може надійти після find
завершення, оскільки загальна команда не чекає завершення команди всередині >(...)
. У цьому bash
ви можете запобігти цьому, додавши | cat
до команди.
>(...)
є (рідко використовується) вихідний процес підстановки , який дозволяє перенаправляти висновок (в даному випадку, STDERR вихід ( 2>
) на стандартне введення командного всередині >(...)
.
Крім того , bash
і zsh
, ksh
підтримує їх, а в принципі , але при спробі об'єднати їх з переадресацією з stderr , як це робиться тут ( 2> >(...)
), здається, мовчки ігнорується (в ksh 93u+
).
grep -v 'Permission denied'
фільтри з ( -v
) все лінії (від find
потоку Stderr командування) , які містять фразу Permission denied
і виводить залишилися рядки в стандартний потік помилок ( >&2
).
Цей підхід:
надійний : grep
застосовується лише до повідомлень про помилки (а не до комбінації шляхів до файлів та повідомлень про помилки, що потенційно призводить до помилкових позитивів), а повідомлення про помилки, окрім відхилених дозволів, передаються в stderr.
Побічний ефект безкоштовно : find
«сек код виходу зберігається: неможливість доступу принаймні один з елементів файлової системи , з якими стикаються результати в вихідному коді 1
(хоча це не про те , який помилки інших відбулося , ніж дозволу, заборонені (теж)).
POSIX-сумісні рішення:
Повністю POSIX-сумісні рішення або мають обмеження, або потребують додаткової роботи.
Якщо find
висновок повинен бути зафіксований у файлі будь-яким чином (або придушений взагалі), то рішення на основі конвеєра відповіді Джонатана Леффлера є простим, надійним та POSIX-сумісним:
find . 2>&1 >files_and_folders | grep -v 'Permission denied' >&2
Зауважте, що порядок переадресацій має значення: 2>&1
повинен бути першим .
Захоплення виводу stdout у передній частині файлу дозволяє 2>&1
надсилати через конвеєр лише повідомлення про помилки, які grep
потім можуть однозначно працювати.
Єдиним недоліком є те, що загальний код виходу буде grep
командування , а НЕ find
«s, що в даному випадку означає: якщо немає жодної помилки на всіх або тільки помилки дозволу, відмовлено, код виходу буде 1
(сигналізації збою ), в іншому випадку ( помилки, відмінні від дозволів, відмовлених у дозволі) 0
- що протилежне наміру.
Однак, find
вихідний код в будь-якому випадку використовується рідко , оскільки він часто передає мало інформації за рамки принципових збоїв, таких як проходження неіснуючого шляху.
Однак конкретний випадок навіть лише деякихз вхідних шляхів бути недоступні з - за відсутність дозволів буде відображений в find
«s коді виходу (як в GNU і BSD find
): якщо помилка дозволу-відмовляв відбувається для будь-якого з оброблюваних файлів, код виходу встановлюються в 1
.
Наступні варіанти адреси, які:
find . 2>&1 >files_and_folders | { grep -v 'Permission denied' >&2; [ $? -eq 1 ]; }
Тепер код виходу вказує, чи були помилки, крім помилок Permission denied
: 1
якщо так, то в 0
іншому випадку.
Іншими словами: код виходу тепер відображає справжній намір команди: повідомляється успіх ( 0
), якщо помилок взагалі не було або лише помилок, відхилених дозволом.
Це, мабуть, навіть краще, ніж просто проходження find
коду виходу через, як у рішенні вгорі.
gniourf_gniourf в коментарях пропонує (все ще сумісні з POSIX) узагальнення цього рішення з використанням складних перенаправлень , що працює навіть при поведінці за замовчуванням друку шляхів файлів до stdout :
{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1
Коротше кажучи: спеціальний дескриптор файлу 3
використовується для тимчасової заміни stdout ( 1
) та stderr ( 2
), щоб лише повідомлення про помилки можна було передати grep
через stdout.
Без цих перенаправлень як дані (шляхи до файлів), так і повідомлення про помилки переносилися б grep
через stdout, і grep
тоді вони не змогли б розрізнити повідомлення про помилку Permission denied
та (гіпотетичний) файл, ім'я якого містить фразу Permission denied
.
Як і в першому рішенні, однак, вихідний код, про який повідомляється, буде grep
's, не find
', але може бути застосовано те саме виправлення, що вище.
Примітки до існуючих відповідей:
Є кілька моментів , щоб відзначити про відповіді Майкла Brux в , find . ! -readable -prune -o -print
:
Це вимагає GNU find
; помітно, він не працюватиме на macOS. Звичайно, якщо вам потрібна лише команда для роботи з GNU find
, це не буде для вас проблемою.
Деякі Permission denied
помилки все ще можуть виникати : find ! -readable -prune
повідомляє про такі помилки для дочірніх елементів каталогів, на які поточний користувач має r
дозвіл, але не має x
(виконуваного) дозволу. Причина полягає в тому, що , оскільки сам каталог є читаним, -prune
не виконується, а спроба спуску в цей каталог , то викликає повідомлення про помилки. Однак, типовим випадком є r
відсутність дозволу.
Примітка. Наступний момент - це питання філософії та / або конкретного випадку використання, і ви можете вирішити, що він не стосується вас і що команда добре відповідає вашим потребам, особливо якщо ви просто робите просто друк шляхів:
- Якщо ви концептуалізуєте фільтрування повідомлень про помилки, відхилені в дозволі, окремим завданням, яке ви хочете застосувати до будь-якої
find
команди, то протилежний підхід проактивного запобігання помилок, відхилених дозволом, вимагає введення команди "шум" у find
команду, яка також вводить складність та логічні підводні камені .
- Наприклад, найголовніший коментар до відповіді Майкла (станом на це написання) намагається показати, як розширити команду, включивши
-name
фільтр, наступним чином:
find . ! -readable -prune -o -name '*.txt'
Це, однак, не працює за призначенням, тому що потрібна остання -print
дія (пояснення можна знайти у цій відповіді ). Такі тонкощі можуть вводити помилки.
Перше рішення в відповідь Джонатан Леффлера , find . 2>/dev/null > files_and_folders
як він сам стверджує, сліпо заглушає всі повідомлення про помилки (і обхідний шлях є громіздким і не в повній мірі надійною, як він пояснює). Практично кажучи , проте це найпростіше рішення , оскільки ви можете бути задоволеними припускати, що будь-які помилки пов'язані з дозволом.
Відповідь Туману , sudo find . > files_and_folders
, є коротким і прагматичним, але необачний для будь-яких інших цілей, ніж просто друк імен файлів , з міркувань безпеки: тому що ви працюєте в якості кореневого користувача « , ви ризикуєте маючи всю систему будучи переплуталися помилкою в знахідку або зловмисна версія, або неправильна виклик, яка пише щось несподівано, що не могло статися, якщо ви запустили це зі звичайними привілеями "(з коментаря до відповіді туману від триплечі ).
Друге рішення в відповідь viraptor в , find . 2>&1 | grep -v 'Permission denied' > some_file
працює ризик помилкових спрацьовувань ( в зв'язку з відправкою поєднання стандартний висновок і стандартний потік помилок по трубопроводу), і, можливо, замість того, щоб повідомляти не є -permission-помилки відмови через STDERR, захоплює їх разом з вихідними шляхами у вихідному файлі.
find . 2>&1 > files_and_folders | grep -v 'Permission denied' >&2
:?