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


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

find . > files_and_folders

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

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

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

18 693

18 ответов:

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

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

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

Примечание: есть небольшой шанс, что некоторые grep'ы выход может прибыть после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выход должен быть захвачен в file в любом случае (или подавляется полностью), то решение на основе конвейера из ответ Джонатана Леффлера просто, робастно, и POSIX-уступчиво:

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

отметим, что порядок перенаправления имеет значение:2>&1 должны прийти первый.

захват вывода stdout в файле спереди позволяет 2>&1 отправить только сообщения об ошибках через трубопровод, который grep может после этого однозначно работать дальше.

The единственным недостатком является то, что общий выход код будет 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 в противном случае.
Другими словами: код выхода теперь отражает истинное намерение команды: success (0) сообщается, если нет ошибок вообще или только разрешение-отказано ошибки произошли.
Это, возможно, даже лучше, чем просто прохождение find ' s код выхода через, как в решении в верхней части.


gniourf_gniourf в комментариях предлагает a (все еще 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, а не find ' s, но то же самое исправление, что и выше, может быть применено.


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

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

    • требует GNUfind; примечательно, что он не будет работать на 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,лаконичен и прагматичен, но не рекомендуется ни для чего, кроме как просто печати имена, по соображениям безопасности: потому что вы работаете как root пользователь", вы рискуете иметь свой вся система была испорчена ошибкой в find или вредоносной версии, или неправильным вызовом, который пишет что-то неожиданно, что не могло произойти, если вы запустили это с обычными привилегиями" (из комментария к ответу mist by tripleee).

  • 2-е решение в viraptor ответ,find . 2>&1 | grep -v 'Permission denied' > some_file существует риск ложных срабатываний (из-за отправки смеси stdout и stderr по конвейеру), и, возможно, вместо этого из отчетности номера-ошибки с запрещенным разрешением через 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 |. Труба перенаправляет стандартный вывод на и применяется в первую очередь. Элемент 2>&1 отправляет стандартную ошибку в то же место, что и стандартный выход (труба). Элемент > files_and_folders отправляет стандартный вывод (но не стандартную ошибку) в файл. Конечным результатом является то, что сообщения, записанные в стандартную ошибку, отправляются по трубе и регулярному выходу find записывается в файл. Элемент grep фильтрует стандартный вывод (вы можете решить, насколько избирательным он должен быть, и, возможно, придется изменить орфографию в зависимости от локали и O/S) и окончательный >&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. Предыстория:

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

см. также find(1) manpage для получения более подробной информации.

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

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 "invert", чтобы не видеть выходные строки, которые имеют пары слов "отказано в разрешении":

    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 Stack Exchange):

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 locale С помощью переменные среды,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]). (Помните, что по умолчанию выражения являются and'D вместе, если вы не используете-or.) Вам нужно-Общ во втором выражении или же find может добавить действие по умолчанию, чтобы показать либо совпадение, которое также покажет вам все нечитаемые файлы.

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

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

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

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

sudo find / -name file.txt

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

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

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

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-follow \
    \ (типа Д -! \ (- readable-a-executable \) \) -чернослив \
    -о \
    \ (типа Д-а-читаемым -а-исполняемый -с -именем "${m_find_name}" \) -печать

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

has read access AND has execute access

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

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

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

вы можете использовать grep-v invert-match

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

такой:

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

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

-=Для MacOS=-

сделать новую команду с помощью псевдонима: просто добавьте в~/.строке файл:

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

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

$ file=<filename or mask>; search

например:

$ file=etc; search

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

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

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

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

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

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

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