Примітка:
* Ця відповідь, ймовірно, йде глибше, ніж вимагає випадок використання, і 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:?