Как я могу исключить все сообщения " отказано в разрешении "из"найти"?

мне нужно скрыть все доступ запрещен сообщения:

find . > files_and_folders

я экспериментирую, когда возникает такое сообщение. Мне нужно собрать все папки и файлы, к которым не возникает.

можно ли направить уровни разрешений на ?

Как я могу скрыть ошибки в то же время?

18 ответов


Примечание:
* Этот ответ, вероятно, идет глубже, чем гарантирует прецедент, и find 2>/dev/null может быть достаточно хорош во многих ситуациях. Он по-прежнему может представлять интерес для кросс-платформенной перспективы и для обсуждения некоторых передовых методов оболочки в интересах поиска решения, которое является как можно более надежным, хотя случаи, защищенные от может быть в значительной степени гипотетическим.
* если ваша система настроена на шоу локализованный ошибка сообщения, перед find вызовы с LC_ALL=C (LC_ALL=C find ...), чтобы убедиться, что английский язык сообщения сообщаются, так что grep -v 'Permission denied' работает, как задумано. Неизменно, однако, любые сообщения об ошибках, которые do get отображается будет также на английском языке.

если shell это bash или zsh, есть решение, которое является надежным, будучи достаточно простым, используя только POSIX-совместимый find особенности, а bash сам по себе не является частью POSIX, большинство современных платформ Unix поставляются с ним, что делает это решение широко переносимым:

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

Примечание: есть небольшой шанс, что некоторые grep's выход может прибыть после find завершается, потому что общая команда не ждет команды внутри >(...) до конца. В bash, вы можете предотвратить это путем добавления | cat к команда.

  • >(...) это (редко используется) выход подмена процесса что позволяет перенаправлять вывод (в этом случае, stderr выход (2>) к stdin команды внутри >(...).
    В дополнение к bash и zsh, ksh поддерживает их также в принципе, но пытается объединить их с перенаправлением из stderr, как это сделано здесь (2> >(...)), представляется молча игнорируется (в ksh 93u+).

    • grep -v 'Permission denied' фильтры из (-v) все строки (с find поток stderr команды), которые содержат фразу Permission denied и выводит оставшиеся строки в stderr (>&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код выхода редко используется в любом случае, поскольку он часто передает мало информации за пределами фундаментальной сбой, такой как прохождение несуществующего пути.
Однако, конкретный случай даже только некоторые входных путей недоступны из-за отсутствия разрешений is отражены в findкод выхода (как в GNU, так и в BSD find): если ошибка разрешения-отказано происходит для любой из обработанных файлов код выхода имеет значение 1.

следующий вариант адресует это:

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

теперь код выхода указывает, есть ли какие-либо ошибки кроме Permission denied произошли: 1 если это так, 0 иначе.
Другими словами: код выхода теперь отражает истинное намерение команды: success (0) сообщается, если нет ошибок вообще или только разрешение-ошибки запрещены.
Это, возможно, даже лучше, чем просто прохождение find ' s код выхода через, как в решении в верхней части.


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, а не find, но то же исправление, что и выше, может быть применено.


примечания к существующему ответы:

  • есть несколько моментов, чтобы отметить о ответ Майкла Брукса, find . ! -readable -prune -o -print:

    • требует GNU find; примечательно, что он не будет работать на macOS. Конечно, если вам нужна только команда для работы с GNU find, это не будет для вас проблемой.

    • некоторые Permission denied ошибки еще поверхность: find ! -readable -prune сообщает о таких ошибках для the ребенок элементы справочников, для которых текущий пользователь имеет r разрешения, но не хватает x (исполняемый) разрешение. Причина в том, что сам каталог is читаемо, -prune не выполняется, а попытка спуска на этот каталог затем запускает сообщения об ошибках. Тем не менее,типичный дело по r разрешение на отсутствие.

    • Примечание.: Следующий пункт является вопросом философии и / или конкретного случая использования, и вы можете решить, что это не имеет отношения к вам и что команда хорошо соответствует вашим потребностям, особенно если просто печати пути-это все, что вы делаете:

      • если вы концептуализировать фильтрации разрешением опроверг сообщения об ошибках в отдельные задача, которую вы хотите иметь возможность применить к любой find команда, затем противоположный подход проактивно предупреждение разрешение-отказано ошибки требует введения " шум " в find команда, которая также вводит сложность и логичность подводные камни.
      • например, самый проголосовавший комментарий к ответу Майкла (на момент написания этой статьи) пытается показать, как расширения команда, включив -name фильтра, следующим образом:
        find . ! -readable -prune -o -name '*.txt'
        Это, однако, делает не работа по назначению, потому что трейлинг -print действие требуются (объяснение можно найти в ответ). Такие тонкости могут вводить ошибки.
  • первое решение в ответ Джонатана Леффлера, find . 2>/dev/null > files_and_folders, как он сам заявляет, слепо молчанку все сообщения об ошибках (и обходной путь громоздок и не полностью надежен, как он также объясняет). говоря прагматично, но это простое решение, поскольку вы можете довольствоваться предположением, что любые ошибки будут связаны с разрешением.

  • туманный ответ, sudo find . > files_and_folders, лаконично и прагматично, но неблагоразумно для чего-либо, кроме просто печати имена, по соображениям безопасности: потому что вы работаете как root пользователь", вы рискуете иметь свой вся система испорчена ошибкой в find или вредоносной версией, или неправильным вызовом, который пишет что-то неожиданно, что не может произойти, если вы запустили это с обычными привилегиями" (из комментария к ответу mist tripleee).

  • 2-е решение в viraptor ответ, find . 2>&1 | grep -v 'Permission denied' > some_file рискует получить ложные срабатывания (из-за отправки смеси stdout и stderr через конвейер), и, возможно, вместо этого отчетности non-разрешение-отказано в ошибках через stderr, захватывает их вместе с выходными путями в выходном файле.


использование:

find . 2>/dev/null > files_and_folders

это скрывает не только Permission denied ошибки, конечно, но все сообщения об ошибках.

если вы действительно хотите сохранить другие возможные ошибки, такие как слишком много прыжков по символической ссылке, но не отказано в разрешении, то вам, вероятно, придется сделать летающее предположение, что у вас не так много файлов под названием "отказано в разрешении" и попробуйте:

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

если вы строго хотите фильтровать только стандартную ошибку, вы можете использовать более сложные строительство:

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

перенаправление ввода/вывода на - это: 2>&1 > files_and_folders |. Труба перенаправляет стандартный вывод на и применяется в первую очередь. The 2>&1 отправляет стандартную ошибку в то же место, что и стандартный выход (труба). The > files_and_folders отправляет стандартный вывод (но не стандартную ошибку) в файл. Конечный результат заключается в том, что сообщения, записанные в стандартную ошибку, отправляются по трубе и регулярному выходу find записывается в файл. The grep фильтрует стандартный вывод (вы можете решить, насколько избирательным он должен быть, и, возможно, придется изменить правописание в зависимости от локали и O/S) и final >&2 означает, что оставшиеся сообщения об ошибках (записанные на стандартный вывод) снова переходят к стандартной ошибке. Окончательное перенаправление можно рассматривать как необязательное в терминале, но было бы очень хорошей идеей использовать его в скрипте, чтобы сообщения об ошибках появлялись при стандартной ошибке.

есть бесконечные вариации на эту тема, в зависимости от того, что вы хотите сделать. Это будет работать на любом варианте Unix с любой производной оболочки Bourne (Bash, Korn,...) и любой POSIX-совместимой версией find.

если вы хотите адаптироваться к конкретной версии find у вас есть в вашей системе, могут быть альтернативные варианты. GNU find в частности, имеет множество опций, недоступных в других версиях-см. принятый в настоящее время ответ для одного такого набора опций.


использование:

find . ! -readable -prune -o -print

или вообще

find <paths> ! -readable -prune -o <other conditions like -name> -print
  • чтобы избежать "отказано в доступе"
  • и не подавлять (другие) сообщения об ошибках
  • и получить статус выхода 0 ("все файлы успешно обработаны")

работает с: find (GNU findutils) 4.4.2. Справочная информация:

  • на -readable тест соответствует читаемым файлам. The ! оператор возвращает true, если test равен false. И ! -readable соответствует нечитаемым каталогам (&файлам).
  • на -prune действие не опускается в каталог.
  • ! -readable -prune можно перевести на: если каталог не читается, не спускайтесь в него.
  • на -readable тест учитывает списки контроля доступа и другие артефакты разрешений, которые -perm тест игнорирует.

см. также find(1) man-страницы для много больше деталей.


если вы хотите начать поиск с корня"/", вы, вероятно, увидите вывод чего-то вроде:

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

это из-за разрешения. Чтобы решить эту проблему:

  1. вы можете использовать команду sudo: sudo find /. -name 'toBeSearched.file'. он спрашивает пароль супер пользователя, когда введите пароль, вы увидите результат, что вы действительно хотите.

  2. вы можете использовать перенаправить стандартный вывод ошибки из (обычно дисплей / экран) в какой-либо файл и избежать просмотра ошибки сообщения на экране! перенаправление в специальный файл / dev / null :

    find /. -name 'toBeSearched.file' 2>/dev/null
    
  3. вы можете использовать перенаправить стандартный вывод ошибок с (Обычно дисплей / экран) на стандартный вывод (обычно дисплей / экран), а затем передать команду grep с параметром-v "инвертировать", чтобы не видеть выходные строки, которые имеют пары слов "разрешение отказано":

    find /. -name 'toBeSearched.file' 2>&1 | grep -v 'Permission denied'
    

мне пришлось использовать:

find / -name expect 2>/dev/null

указав имя того, что я хотел найти, а затем сказав ему перенаправить все ошибки в /dev/null

ожидайте, что это местоположение ожидаемой программы, которую я искал.


труба stderr до /dev/null С помощью 2>/dev / null

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


вы также можете использовать -perm и -prune предикаты, чтобы избежать спуска в нечитаемые каталоги (см. также Как удалить инструкции распечатки "отказано в разрешении" из программы поиска? - В Unix И Linux Стек Обмен):

find . -type d ! -perm -g+r,u+r,o+r -prune -o -print > files_and_folders

перенаправить стандартный поток ошибок. Например, если вы используете bash на машине unix, вы можете перенаправить стандартную ошибку в /dev / null следующим образом:

find . 2>/dev/null >files_and_folders

в то время как вышеуказанные подходы не затрагивают случай для Mac OS X, потому что Mac Os X не поддерживает -readable переключатель вот как вы можете избежать ошибок "отказано в разрешении" в вашем выходе. Это может кому-то помочь.

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

если вы используете другую команду с find, например, чтобы найти размер файлов определенного шаблона в каталоге 2>/dev/null будет работать, как показано ниже.

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

это вернет общее размер файлов заданного шаблона. Примечание 2>/dev/null В конце команды find.


эти ошибки выводятся на стандартный вывод ошибок (fd 2). Чтобы отфильтровать их, просто перенаправьте все ошибки в /dev / null:

find . 2>/dev/null > some_file

или сначала присоединитесь к stderr и stdout, а затем grep из этих конкретных ошибок:

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

простой ответ:

find . > files_and_folders 2>&-

2>&- закрывается (-) стандартный дескриптор файла ошибок (2), чтобы все сообщения об ошибках отключены.

  • код выхода по-прежнему будет 1 если 'Permission denied' ошибки в противном случае будут напечатаны

надежный ответ для GNU find:

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

передать дополнительные опции в find что -prune (предотвратить спуск в), но все же -print любой директории (-typed), что не (\!) имеют как -readable и -executable разрешения, или (-o) -print любой другой файл.

  • -readable и -executable параметры являются расширениями GNU, а не частью в POSIX стандарт
  • может еще вернется 'Permission denied ' об аномальных / поврежденных файлах (например, см. сообщить об ошибке влияние на файловые системы, смонтированные в контейнере, с помощью lxcfs

надежный ответ, который работает с любым POSIX-совместимым find (GNU, OSX / BSD и т.д.)

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

использовать трубопровод передать стандартный поток ошибок в grep удаление всех строк, содержащих 'Permission denied' строку.

LC_ALL=C задает локаль POSIX С помощью переменные среды, 3>&2 2>&1 1>&3 и 3>&2 2>&1 дублирования файловых дескрипторов для передачи потока стандартных ошибок в grep и [ $? = 1 ] использует [] инвертировать код ошибки, возвращенный grep чтобы приблизиться к исходному поведению find.

  • также будет фильтровать любым 'Permission denied' ошибки, связанные для вывода перенаправления (например, если files_and_folders сам файл не доступен для записи)

избежать просто в разрешении отказано предупреждения, скажите find игнорировать нечитаемые файлы, обрезая их из поиска. Добавьте выражение как или в свою находку, например

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

это в основном говорит (сопоставьте нечитаемый файл и удалите его из списка) или (совпадение имени, как *.компании jbd и отобразить его [с ls]). (Помните, что по умолчанию выражения и вместе, если вы не используете-или.) Вам нужно-ls во втором выражении или find может добавить действие по умолчанию, чтобы показать любое совпадение, которое также покажет вам все нечитаемые файлы.

но если вы ищете реальные файлы в своей системе, обычно нет причин искать в /dev, в котором много файлов, поэтому вы должны добавить выражение, исключающее этот каталог, например:

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

Так (матч нечитаемый файл и чернослив из списка) или (путь /dev и чернослив из списка) или файл(матч, как *.компании jbd и отображать его).


использовать

sudo find / -name file.txt

это глупо (потому что вы повышаете поиск) и небезопасно, но гораздо короче писать.


ни один из вышеперечисленных ответов работал для меня. Все, что я нахожу в Интернете, фокусируется на: скрыть ошибки. Не правильно обрабатывает процесс возврата-код / выход-код. Я использую команду find в сценариях bash, чтобы найти некоторые каталоги, а затем проверить их содержимое. Я оцениваю команду find success с помощью exit-code: значение zero работает, в противном случае терпит неудачу.

на ответ выше by Майкл Брукс работает иногда. Но у меня есть один сценарий, в котором он терпит неудачу! Я обнаружил проблему и решил ее сам. Мне нужно обрезать файлы, когда:

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

см. ключевой вопрос здесь: и / или. Одна хорошая предложенная последовательность условий, которую я читаю:

-type d ! -readable ! -executable -prune

это не всегда работает. Это означает, что чернослив запускается, когда матч:

it is directory AND no read access AND no execute access

эта последовательность выражений терпит неудачу, когда доступ на чтение предоставлен, но нет доступа на выполнение.

после некоторого тестирования я понял, об этом и изменил мой скрипт решение:

nice find / home* / - maxdepth 5-Следуйте \
    \ (типа Д -! \ (- читаемый-исполняемый файл\) \) -чернослив \
    - o \
    \ (- type d-A-readable-a-executable-a-name " ${m_find_name}"\) - печать

ключ здесь должен поместить "не true" для комбинированного выражения:

has read access AND has execute access

в противном случае он не имеет полного доступа, что означает: обрезать его. Это оказалось для меня полезным. в одном сценарии, который предыдущие предлагаемые решения не удалось.

Я предоставляю ниже технические подробности для вопросов в разделе комментариев. Прошу прощения, если подробности излишни.

  • Why почему с помощью команды nice? У меня есть идея здесь. Сначала я подумал, что было бы неплохо уменьшить приоритет процесса при просмотре всей файловой системы. Я понял, что для меня это не имеет смысла, так как мой скрипт ограничен несколькими каталогами. Я уменьшил-maxdepth до 3.
  • Why зачем искать внутри / home*/? Это не относится к данной теме. Я устанавливаю все приложения вручную через компиляцию исходного кода с непривилегированными пользователями (не root). Они установлены внутри "/ home". У меня может быть несколько двоичных файлов и версий, живущих вместе. Мне нужно найти все каталоги, проверить и создать резервную копию в режиме master-slave. У меня может быть несколько" / home " (несколько дисков, работающих на выделенном сервере).
  • Why почему используя-следовать? Пользователи могут создание символических ссылок на каталоги. Это зависит от полезности, мне нужно вести учет найденных абсолютных путей.

вы можете использовать инвертный матч grep-v

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

такой:

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

следует к магии


-=Для MacOS=-

создайте новую команду, используя псевдоним: просто добавьте~/.bash_profile line:

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

и в новом окне терминала можно назвать:

$ file=<filename or mask>; search

например:

$ file=etc; поиск


Если вы используете CSH или TCSH, вот решение:

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

Если вы хотите выводить на терминал:

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

однако, как описано в FAQ" csh-whynot", вы не должны использовать CSH.


вы также простое решение положить ваши результаты поиска в файл.

найти . - имя 'NameOfSearchedFile' > > результаты.txt