Примечание:
* Этот ответ, вероятно, идет глубже, чем оправдывает сценарий использования, и 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> >(...)
), кажется, игнорируется (in ksh 93u+
).
grep -v 'Permission denied'
фильтры из ( -v
) все линии (от find
потока Stderr командования) , которые содержат фразу Permission denied
и выводит оставшиеся строки в стандартный поток ошибок ( >&2
).
Этот подход:
robust : grep
применяется только к сообщениям об ошибках (но не к комбинации путей к файлам и сообщений об ошибках, которые могут привести к ложным срабатываниям), а сообщения об ошибках, отличные от запрещенных, передаются в stderr.
Побочный эффект бесплатно : find
«сек код выхода сохраняется: невозможность доступа по крайней мере один из элементов файловой системы , с которыми сталкиваются результаты в выходном коде 1
(хотя это не о том , какой ошибки других произошло , чем разрешения, запрещённые (тоже)).
POSIX-совместимые решения:
Полностью POSIX-совместимые решения либо имеют ограничения, либо требуют дополнительной работы.
Если find
выход «S должен быть захвачен в файл в любом случае (или подавлена вообще), то трубопровод на основе решения от ответа Джонатана Леффлера является простым, надежным и 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
коде выхода России (как в 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-совместимое) обобщение этого решения с использованием сложных перенаправлений , которое работает даже при стандартном поведении печати путей к файлу на стандартный вывод :
{ 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
, является кратким и прагматичным, но опрометчивый для любых других целей, чем просто печать имен файлов , по соображениям безопасности: потому что вы работаете в качестве корневого пользователя « , вы рискуете имея всю систему будучи перепутались ошибкой в находке или вредоносная версия, или неправильный вызов, который пишет что-то неожиданно, что не может произойти, если вы запустили это с обычными привилегиями »(из комментария к ответу тумана от tripleee ).
Второе решение в ответ viraptor в , find . 2>&1 | grep -v 'Permission denied' > some_file
работает риск ложных срабатываний ( в связи с отправкой сочетание стандартный вывод и стандартный поток ошибок по трубопроводу), и, возможно, вместо того, чтобы сообщать не являющихся -permission-ошибки отказа через STDERR, захватывает их вместе с выходными путями в выходном файле.
find . 2>&1 > files_and_folders | grep -v 'Permission denied' >&2
:?