Мне нужно скрыть все отклоненные отклонения от сообщений:
find . > files_and_folders
Я экспериментирую, когда возникает такое сообщение. Мне нужно собрать все папки и файлы, к которым это не возникает.
Можно ли направить уровни разрешений в файл files_and_folders
?
Как я могу скрыть ошибки одновременно?
Примечание:
* Этот ответ, вероятно, идет глубже, чем ордера на использование, и 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>
) в stdin команды внутри >(...)
.
В дополнение к bash
и zsh
, ksh
также поддерживает их в принципе, но попытка объединить их с перенаправлением из stderr, как это делается здесь (2> >(...)
), кажется молча игнорируемой (в ksh 93u+
).
grep -v 'Permission denied'
отфильтровывает (-v
) все строки (из потока stderr команды find
), которые содержат фразу Permission denied
, и выводит оставшиеся строки на stderr (>&2
).Этот подход:
надежный: grep
применяется только к сообщениям об ошибках (а не к комбинациям путей к файлам и сообщениям об ошибках, что может привести к ложным срабатываниям) и сообщения об ошибках, отличные от разрешения -пределенные передаются через stderr.
свободный от побочного эффекта: find
код выхода сохраняется: невозможность доступа хотя бы к одному из найденных элементов файловой системы в код выхода 1
(хотя это выиграло ' t сообщите, произошли ли ошибки, отличные от разрешенных прав).
Полностью совместимые с POSIX решения либо имеют ограничения, либо требуют дополнительной работы.
Если вывод find
должен быть сохранен в файле в любом случае (или вообще подавлен), тогда решение на основе трубопровода из Джонатан Леффлер ответит является простым, надежным и совместимым с POSIX:
find . 2>&1 >files_and_folders | grep -v 'Permission denied' >&2
Обратите внимание, что порядок перенаправления имеет значение: 2>&1
должен быть первым.
Захват вывода stdout в фронте файла позволяет 2>&1
отправлять только сообщения об ошибках по конвейеру, которые grep
может затем недвусмысленно работать.
Единственным недостатком является то, что общий код выхода будет <<2 → grep
, а не find
', что в данном случае означает: если ошибок нет или только разрешение -пределенные ошибки, код выхода будет 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
exit, как в решении вверху.
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
', но можно применить те же исправления, что и выше.
Есть несколько моментов, чтобы отметить ответ Майкла Брукса, 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
, как он сам утверждает, слепо молчает все сообщения об ошибках ( и обходной путь является громоздким и не полностью надежным, как он объясняет). Прагматично говоря, однако, это простейшее решение, так как вы можете быть довольным предположить, что любые и все ошибки будут связаны с разрешением.
answer answer, sudo find . > files_and_folders
, является кратким и прагматичным, но не рекомендуется ни для чего другого, кроме простого для печати имен файлов, по соображениям безопасности: поскольку вы работаете как пользователь root, "вы рискуете, что вся ваша система запуталась в ошибке поиска или вредоносной версии или неправильном вызове, который пишет что-то неожиданное, чего не может быть, если вы запускал это с обычными привилегиями" (из комментария к туманному ответу tripleee).
Второе решение в ответе viraptor, find . 2>&1 | grep -v 'Permission denied' > some_file
запускает риск ложных срабатываний (из-за отправки комбинации stdout и stderr по конвейеру), и, возможно, вместо того, чтобы сообщать о недопустимых ошибках через stderr, захватывает их вместе с выходными путями в выходном файле.
Использование:
find . 2>/dev/null > files_and_folders
Это скрывает не только разрешение, допускающее ошибки, но все сообщения об ошибках.
Если вы действительно хотите сохранить другие возможные ошибки, например, слишком много переходов на символической ссылке, но не на отказ от отказа, тогда вам, вероятно, придется взять летное предположение, что у вас не так много файлов, разрешение отклонено "и попробуйте:
find . 2>&1 | grep -v 'permission denied' > files_and_folders
Если вы строго хотите фильтровать только стандартную ошибку, вы можете использовать более сложную конструкцию:
find . 2>&1 > files_and_folders | grep -v 'permission denied' >&2
Перенаправление ввода-вывода в команде find
: 2>&1 > files_and_folders |
.
Труба перенаправляет стандартный вывод в команду grep
и применяется сначала. 2>&1
отправляет стандартную ошибку на то же место, что и стандартный вывод (труба). > files_and_folders
отправляет стандартный файл (но не стандартную ошибку) в файл. Конечным результатом является то, что сообщения, записанные в стандартную ошибку, отправляются по каналу, и в файл записывается обычный вывод find
. grep
фильтрует стандартный вывод (вы можете решить, насколько избирательным вы его хотите, и, возможно, придется менять орфографию в зависимости от языка и O/S), а окончательный >&2
означает, что оставшиеся сообщения об ошибках (записанные на стандартный выход) еще раз перейдите к стандартной ошибке. Окончательное перенаправление можно рассматривать как необязательное на терминале, но было бы очень неплохо использовать его в script, чтобы сообщения об ошибках отображались при стандартной ошибке.
В этой теме бесконечные вариации, в зависимости от того, что вы хотите сделать. Это будет работать над любым вариантом Unix с любой производной оболочки Bourne (Bash, Korn,...) и любой версией find
.
Если вы хотите адаптироваться к конкретной версии find
, которая у вас есть в вашей системе, могут быть доступны альтернативные варианты. GNU find
, в частности, имеет множество параметров, недоступных в других версиях - см. Текущий принятый ответ для одного такого набора параметров.
2>/dev/null
, без пробела!
2>
- это единое целое без пробелов; между ним и именем файла может быть пробел. Аналогично с другими перенаправлениями, такими как 2>&1
(который перенаправляет стандартную ошибку в то же место, где происходит стандартный вывод), или 2>&-
который закрывает стандартную ошибку, и т. Д. См. Перенаправления для получения дополнительной информации о кровопролитии. (Приведенный выше код является общей оболочкой, подобной POSIX, а не специфичной для bash
.)
Использование:
find . ! -readable -prune -o -print
или в целом
find <paths> ! -readable -prune -o <other conditions like -name> -print
Работает с: find (GNU findutils) 4.4.2. Справочная информация:
-readable
соответствует читаемым файлам. Оператор !
возвращает true, когда тест является ложным. И ! -readable
соответствует не читаемым каталогам (& файлы).-prune
не входит в каталог.! -readable -prune
можно перевести на: если каталог не читается, не входите в него.-readable
учитывает списки управления доступом и другие артефакты разрешений, которые игнорирует тест -perm
.См. также справочную страницу (1) для более подробной информации.
Если вы хотите начать поиск с корневого "/", вы, вероятно, увидите что-то вроде:
find: /./proc/1731/fdinfo: Permission denied
find: /./proc/2032/task/2032/fd: Permission denied
Это из-за разрешения. Чтобы решить эту проблему:
Вы можете использовать команду sudo: sudo find /. -name 'toBeSearched.file'
. он запрашивает пароль суперпользователя, когда вы вводите пароль, вы увидите результат, который вы действительно хотите.
Вы можете перенаправить стандартный вывод ошибки (обычно дисплей/экран) на какой-либо файл и не видеть сообщения об ошибках на экране! перенаправить на специальный файл /dev/null:
find /. -name 'toBeSearched.file' 2>/dev/null
Вы можете перенаправить стандартный вывод ошибки (обычно дисплей/экран) на стандартный вывод (обычно дисплей/экран), затем выполнить команду grep с параметром -v "инвертировать", чтобы не видеть выходные линии который содержит пары слов "Разрешение отказа":
find /. -name 'toBeSearched.file' 2>&1 | grep -v 'Permission denied'
sudo find...
Мне пришлось использовать:
find / -name expect 2>/dev/null
указав имя того, что я хотел найти, а затем сообщив ему перенаправить все ошибки в /dev/null
Предположим, что это место ожидаемой программы, которую я искал.
expect
. Вместо этого expect
- это просто имя файла, который попытается найти эта команда.
Труба stderr
до /dev/null
с помощью 2 > /dev/null
find . -name '...' 2>/dev/null
find . -name '...' -print 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
-perm -g+r,u+r,o+r
просто сопоставляет файлы, для которых установлены разрешения r
(чтение) для всех 3 участников безопасности файла , что не имеет прямого отношения к тому, может ли текущий пользователь прочитать этот файл или не. Он может пропустить файлы, которые текущий пользователь может прочитать, и сопоставить файлы, которые он не может.
find . -type d ! \( -perm -u+r -o -perm -g+r -o -perm -o+r \) -prune -o -print
было бы хорошим решением.
Переназначить стандартную ошибку. Например, если вы используете 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.
2>/dev/null
. Можете ли вы объяснить часть -exec du -ch {} + 2>/dev/null | grep total$
.
-exec
чтобы выполнить дальнейшие действия с файлами или каталогами, найденными командой find
. du -ch file_pattern
вычисляет размер каждого файла, совпадающего с file_pattern
и последняя строка этого вывода представляет собой общую сумму всех файлов, которые соответствуют file_pattern
. Смотрите man-страницу для du
. grep total
просто фильтрует строку, которая извлекает общий итог (последняя строка).
Эти ошибки выводятся на стандартный вывод ошибки (fd 2). Чтобы отфильтровать их, просто переадресуйте все ошибки в /dev/null:
find . 2>/dev/null > some_file
или сначала присоедините stderr и stdout, а затем вычеркните эти конкретные ошибки:
find . 2>&1 | grep -v 'Permission denied' > some_file
find . > files_and_folders 2>&-
2>&-
закрывает (-
) стандартный дескриптор файла ошибки (2
), поэтому все сообщения об ошибках отключены.
1
, если в противном случае будут напечатаны ошибки <<25 > find
: find . -type d \! \( -readable -executable \) -prune -print -o -print > files_and_folders
Передайте дополнительные опции find
, которые -prune
(не спускайтесь), но -print
любой каталог (-type
d
), который не (\!
) имеют -readable
и -executable
или (-o
) -print
любой другой файл.
-readable
и -executable
параметры Расширения GNU, а не часть стандарт POSIXPermission denied
' в ненормальные/поврежденные файлы (например, см. отчет об ошибках, влияющий на файловые системы, монтируемые на контейнерах, с помощью lxcfs
< v2.0.5)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
не доступен для записи)использование
sudo find / -name file.txt
Это глупо (потому что вы поднимаете поиск) и небезопасно, но гораздо короче, чтобы писать.
Чтобы избежать только запрещенных разрешений, скажите find, чтобы игнорировать нечитаемые файлы, обрезая их из поиска. Добавьте выражение как OR к вашей находке, например
find / \! -readable -prune -o -name '*.jbd' -ls
В основном это говорит (сопоставьте нечитаемый файл и обрезайте его из списка) ИЛИ (сопоставьте имя, например *.jbd, и покажите его [с помощью ls]). (Помните, что по умолчанию выражения AND'd вместе, если вы не используете -or.) Вам нужно использовать -ls во втором выражении, иначе find может добавить действие по умолчанию, чтобы показать либо совпадение, которое также покажет вам все нечитаемые файлы.
Но если вы ищете реальные файлы в своей системе, обычно нет причин для поиска в /dev, у которого много файлов, поэтому вы должны добавить выражение, исключающее этот каталог, например:
find / -mount \! -readable -prune -o -path /dev -prune -o -name '*.jbd' -ls
Итак, (совпадающий с нечитаемым файлом и черновик из списка) ИЛИ (путь соответствия /dev и обрезка из списка) ИЛИ (файл соответствия, например *.jbd, и его отображение).
Вы можете использовать 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
Должно к магии
Ни один из вышеперечисленных ответов не работал у меня. Все, что я нахожу в Интернете, фокусируется на: спрятать ошибки. Ни один из них не обрабатывает обратный код процесса/код выхода. Я использую команду find в сценариях bash, чтобы найти некоторые каталоги, а затем проверить их содержимое. Я оцениваю успех поиска команды с помощью кода exit: нулевое значение работает, в противном случае терпит неудачу.
Ответ представленный выше Майкл Брюкс работает иногда. Но у меня есть один сценарий, в котором он терпит неудачу! Я обнаружил проблему и исправил ее сам. Мне нужно обрезать файлы, когда:
it is a directory AND has no read access AND/OR has no execute access
См. ключевую проблему: AND/OR. Одна хорошая рекомендуемая последовательность условий, которую я прочитал:
-type d ! -readable ! -executable -prune
Это не работает всегда. Это означает, что черновик вызывается, когда совпадение:
it is directory AND no read access AND no execute access
Эта последовательность выражений терпит неудачу, если предоставляется доступ для чтения, но не имеет доступа к выполнению.
После некоторого тестирования я понял об этом и изменил решение моей оболочки script на:
nice find/home */-maxdepth 5 -follow\
\(-type d -a !\(-readable -a -executable \) \) -prune\
-o\
\(-type d -a -readable -a -executable -a -name" ${m_find_name} "\) -print
Ключ здесь состоит в том, чтобы поместить "неправда" для комбинированного выражения:
has read access AND has execute access
В противном случае он не имеет полного доступа, что означает: обрезать его. Это оказалось для меня одним сценарием, который ранее не предлагал решения.
Ниже приводятся технические детали для вопросов в разделе комментариев. Приносим извинения, если детали чрезмерны.
nice
и find $HOME -maxdepth 5 -follow ...
?
${m_find_name}
) и содержит несколько параметров, не относящихся к данному вопросу ( nice
, /home*
, -maxdepth 5
, -follow
). Я добавил ответ, который более конкретно решает проблему «фильтрации читаемых, но не исполняемых каталогов», оставаясь при этом универсальным.
- = Для MacOS = -
Создайте новую команду, используя псевдоним: просто добавьте строку ~/.bash_profile:
alias search='find / -name $file 2>/dev/null'
и в новом окне терминала вы можете вызвать его:
$ file=<filename or mask>; search
например:
$file = etc; поиск
Вы также можете легко найти результаты поиска в файле.
найти. -name 'NameOfSearchedFile' → results.txt
find . 2>&1 > files_and_folders | grep -v 'Permission denied' >&2
?{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1