如何从“查找”中排除所有“权限被拒绝”的消息?

时间:2009-04-17 21:54:07

标签: bash error-handling find file-permissions

我需要隐藏所有权限被拒绝的消息:

find . > files_and_folders

我正在尝试这样的消息出现时。我需要收集所有不会出现的文件夹和文件。

是否可以将权限级别定向到files_and_folders文件?

如何同时隐藏错误?

20 个答案:

答案 0 :(得分:527)

使用:

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

find命令的I / O重定向为:2>&1 > files_and_folders |。 管道将标准输出重定向到grep命令并首先应用。 2>&1将标准错误发送到与标准输出(管道)相同的位置。 > files_and_folders将标准输出(但不是标准错误)发送到文件。最终结果是写入标准错误的消息沿管道发送,find的常规输出写入文件。 grep过滤标准输出(您可以决定您希望它具有多大的选择性,并且可能必须根据区域设置和操作系统更改拼写),最终>&2表示存活错误消息(写入标准输出)再次转到标准错误。最终的重定向在终端上可以被视为可选的,但在脚本中使用它是一个非常好的主意,以便在标准错误中出现错误消息。

这个主题有无穷无尽的变化,取决于你想做什么。这适用于任何带有任何Bourne shell衍生物(Bash,Korn,...)和任何符合POSIX的find版本的Unix版本。

如果您希望适应系统中find的特定版本,可能会有其他选项。 GNU find特别具有其他版本中无法提供的无数选项 - 请参阅当前接受的一组选项的答案。

答案 1 :(得分:268)

使用:

find . ! -readable -prune -o -print

或更一般地

find <paths> ! -readable -prune -o <other conditions like -name> -print
  • 避免&#34;权限被拒绝&#34;
  • 并且不禁止(其他)错误消息
  • 并获取退出状态0(&#34;所有文件都已成功处理&#34;)

适用于:find(GNU findutils)4.4.2。 背景:

  • -readable测试与可读文件匹配。当test为false时,!运算符返回true。并且! -readable匹配不可读的目录(&amp; files)。
  • -prune操作不会进入目录。
  • ! -readable -prune可以翻译为:如果目录不可读,请不要进入。
  • -readable测试考虑了-perm测试忽略的访问控制列表和其他权限假象。

有关更多详细信息,另请参阅find(1) manpage

答案 2 :(得分:224)

注意:
*这个答案可能比用例保证更深入,find 2>/dev/null在许多情况下可能已经足够好了。对于跨平台的观点以及为了找到尽可能强大的解决方案而讨论一些先进的shell技术可能仍然有意义,即使防范的案例可能在很大程度上是假设的。 * 如果您的系统配置为显示本地化错误消息,请使用findLC_ALL=C)为LC_ALL=C find ...以下grep -v 'Permission denied'来电添加前缀,以确保报告英语消息,以便bash按预期工作。但是,任何 显示的错误消息都会以英语显示。功能

如果你的 shell是zshfind ,那么一个非常强大而且相当简单的解决方案,使用< strong>仅符合POSIX标准bash功能;虽然find . > files_and_folders 2> >(grep -v 'Permission denied' >&2) 本身不是POSIX的一部分,但大多数现代Unix平台都附带它,使这个解决方案具有广泛的可移植性:

grep

注意:在 find完成后,某些>(...)的输出很可能会到达,因为整体命令并非如此; t等待bash内的命令完成。在| cat中,您可以通过在命令中附加>(...)来阻止此操作。

  • 2>是一个(很少使用)输出 process substitution,它允许重定向输出(在本例中为 stderr 输出({ {1}})>(...)内命令的标准输入 除了bashzsh之外,ksh原则上也支持 ,但尝试将它们与来自 stderr 的重定向相结合,就像这里所做的那样(2> >(...)),似乎被默默忽略(在ksh 93u+中)。

    • grep -v 'Permission denied'过滤 out -v)包含短语{{1}的所有行(来自find命令的stderr流)并将剩余的行输出到stderr(Permission denied)。

这种方法是:

  • 健壮>&2仅适用于错误消息(而不是文件路径和错误消息的组合,可能导致错误积极的),以及除了权限被拒绝的错误消息传递给stderr。

  • 免费副作用grep的退出代码被保留:无法访问至少一个遇到的文件系统项导致退出代码{ {1}}(虽然这不会告诉您错误其他是否也发生了许可拒绝的错误)。

符合POSIX标准的解决方案:

完全符合POSIX标准的解决方案要么有局限性,要么需要额外的工作。

如果要在文件中 (或完全取消)捕获find的输出,那么基于管道的解决方案来自Jonathan Leffler's answer简单,强大且符合POSIX标准:

1

请注意,重定向的顺序很重要:find必须首先

预先在文件中捕获stdout输出允许find . 2>&1 >files_and_folders | grep -v 'Permission denied' >&2 通过管道发送错误消息,然后2>&1可以明确地操作。

唯一的缺点是整体退出代码将是2>&1命令,而不是grep&#39; s,在这种情况下意味着:如果完全存在 no 错误或权限被拒绝错误,则退出代码将为grep(信令失败),否则(除了权限被拒绝的错误)find - 这与意图相反。
也就是说,1的退出代码很少被使用,因为它通常会传递除基本失败之外的一些信息,例如传递不存在的信息路径。
但是,即使只有某些输入路径由于缺少权限而无法访问的特定情况也会反映在0的退出代码中(在GNU和BSD find)中:如果处理的任何文件发生权限被拒绝,则退出代码设置为find

以下变体解决了:

find

现在,退出代码指示是否发生 1以外的任何错误:find . 2>&1 >files_and_folders | { grep -v 'Permission denied' >&2; [ $? -eq 1 ]; } 如果是,Permission denied否则。1。 换句话说:退出代码现在反映了命令的真实意图:如果没有错误或仅发生 权限拒绝错误,则报告成功(0)。
这可以说比通过0的退出代码更好,就像在顶部的解决方案中一样。

评论中的

gniourf_gniourf提出了一个(仍然符合POSIX标准)使用复杂重定向来概括此解决方案,即使使用打印文件路径的默认行为也能正常工作标准输出

find

简而言之:自定义文件描述符{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1 用于临时交换stdout(3)和stderr(1),因此单独的错误消息 可以通过stdout传送到2

如果没有这些重定向,数据(文件路径)错误消息将通过stdout传送到grepgrep将无法区分< em>错误消息 grep和一个(假设的)文件,其名称恰好包含短语Permission denied

与第一个解决方案一样,报告的退出代码为Permission denied,而不是grep,但可以应用与上述相同的修复

关于现有答案的说明:

  • 有关Michael Brux's answerfind的几点注意事项:

    • 它需要 GNU find . ! -readable -prune -o -print;值得注意的是,它不会在macOS上工作。当然,如果您只需要使用命令来处理GNU find,那么这对您来说不会有问题。

    • 某些find错误可能表面:Permission denied报告当前用户的目录项的此类错误是否拥有find ! -readable -prune权限,但缺少r(可执行)权限。原因是因为目录本身可读的,所以x没有执行,并且尝试将下降到该目录然后触发错误消息。也就是说,典型的案例是-prune允许丢失的。

    • 注意:以下几点是哲学和/或特定用例的问题,您可能认为它与您无关,并且该命令可以很好地满足您的需求,特别是如果只是打印< / em>路径就是你所做的一切:

      • 如果您将权限被拒绝错误消息的过滤概念化为单独的任务,您希望该任务能够应用于任何 { {1}}命令,然后主动阻止权限拒绝错误的相反方法需要引入&#34; noise&#34;进入r命令,这也引入了复杂性和逻辑陷阱
      • 例如,对迈克尔答案(截至撰写本文时)的最高投票评论试图通过包含find过滤器来展示如何扩展命令,如下:
        find
        但是,按预期工作,因为尾随-name操作必需(可以在this answer中找到解释)。这种微妙之处可能会引入错误。
  • Jonathan Leffler's answer中的第一个解决方案,find . ! -readable -prune -o -name '*.txt',正如他自己所说,盲目地沉默所有错误消息(以及解决方法)他解释说,这很麻烦而且不够完整。 务实地说,但它是最简单的解决方案,因为您可能会满足于假设任何和所有错误都与权限相关。

  • mist's answer-print简明实用,但除了打印文件名之外的其他任何内容都是不明智的,安全原因:因为您作为 root 用户运行,&#34;您可能会因查找或恶意版本中的错误或不正确的调用而导致整个系统混乱意外地写了一些东西,如果你用正常的权限运行它就不会发生这种情况。 (来自tripleee对雾的答案的评论)。

  • viraptor's answer中的第二个解决方案,find . 2>/dev/null > files_and_folders存在误报的风险(由于通过管道发送混合的stdout和stderr),并且可能不会报告<通过stderr将em> non -permission-denied错误捕获,并将它们与输出文件中的输出路径一起捕获。

答案 3 :(得分:107)

如果你想从根“/”开始搜索,你可能会看到输出的东西,如:

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. 您可以使用标准错误输出从(一般显示/屏幕)重定向到标准输出(一般显示/屏幕),然后使用带有-v“invert”参数的grep命令管道,以便不看输出线其中有“权限被拒绝”字对:

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

答案 4 :(得分:88)

我不得不使用:

find / -name expect 2>/dev/null

指定我想要查找的名称,然后告诉它将所有错误重定向到/ dev / null

期待成为我正在寻找的期待计划的位置。

答案 5 :(得分:54)

使用 2&gt; / dev / null

stderr导管到/dev/null

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

答案 6 :(得分:29)

您还可以使用-perm-prune谓词来避免降级到不可读的目录(另请参阅How do I remove "permission denied" printout statements from the find program? - Unix & Linux Stack Exchange):

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

答案 7 :(得分:23)

重定向标准错误。例如,如果你在unix机器上使用bash,你可以将标准错误重定向到/ dev / null,如下所示:

find . 2>/dev/null >files_and_folders

答案 8 :(得分:19)

虽然上述方法无法解决Mac OS X的问题,因为Mac OS X不支持a { color: #c54bb7 !important; (it's a sort of red) text-decoration: none !important; } 切换,但您可以避免输出中出现“权限被拒绝”错误。这可能对某人有所帮助。

-readable

例如,如果您使用find / -type f -name "your_pattern" 2>/dev/null的其他命令,要查找目录find中某些模式的文件大小,仍然可以如下所示。

2>/dev/null

这将返回给定模式的文件的总大小。请注意find命令末尾的find . -type f -name "your_pattern" -exec du -ch {} + 2>/dev/null | grep total$

答案 9 :(得分:13)

这些错误打印到标准错误输出(fd 2)。要过滤掉它们,只需将所有错误重定向到/ dev / null:

find . 2>/dev/null > some_file

或首先加入stderr和stdout然后grep out那些特定的错误:

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

答案 10 :(得分:10)

简单回答:

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任何目录(-type d) (\!)拥有-readable-executable权限,或(-o-print任何其他文件。

  • -readable-executable选项是GNU扩展,不属于POSIX standard
  • 可能仍会在异常/损坏的文件上返回“Permission denied”(例如,请参阅bug report使用lxcfs&lt; v2.0.5来影响装有容器的文件系统

适用于任何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

使用pipeline将标准错误流传递给grep,删除包含'Permission denied'字符串的所有行。

LC_ALL=C使用POSIX locale3>&2 2>&1 1>&33>&2 2>&1 environment variable设置duplicate file descriptors,以便将标准错误流传输到grep[ $? = 1 ]使用[]来反转grep返回的错误代码,以接近find的原始行为。

  • 还会过滤由于输出重定向导致的任何'Permission denied'错误(例如,如果files_and_folders文件本身不可写)

答案 11 :(得分:4)

使用

sudo find / -name file.txt

这是愚蠢的(因为你提升了搜索)和非安全,但写得更短。

答案 12 :(得分:4)

要避免只是权限被拒绝的警告,请告诉find通过从搜索中删除它们来忽略不可读的文件。将表达式作为OR添加到您的查找中,例如

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

这主要是指(匹配一个不可读的文件并从列表中删除它)(匹配一个名称,如 * .jbd 并显示它[与LS])。 (请记住,除非你使用-or,否则默认情况下表达式是AND。)你需要在第二个表达式中使用-ls,否则find可以添加一个默认动作来显示匹配,这也会显示所有不可读的文件

但是如果你在你的系统上寻找真实文件,通常没有理由查看/ dev,它有很多文件,所以你应该添加一个排除该目录的表达式,如:

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

所以(匹配不可读的文件和从列表中删除)(匹配路径/ dev和从列表中删除)(匹配文件,如 * .jbd 并显示它)

答案 13 :(得分:2)

上述答案都不适合我。无论我在互联网上发现什么,重点是:隐藏错误。没有正确处理进程返回代码/退出代码。我在bash脚本中使用命令查找一些目录,然后检查它们的内容。我使用退出代码评估命令查找成功:值零工作,否则失败。

answer provided above Michael Brux有时可以正常工作。但我有一个失败的场景!我发现了这个问题并自己解决了。我需要在以下时间修剪文件:

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

当授予读访问权但没有执行访问权时,此表达式序列失败。

经过一些测试后,我意识到这一点并将我的shell脚本解决方案更改为:

  

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

这里的关键是将“not true”放在组合表达式中:

has read access AND has execute access

否则它没有完全访问权限,这意味着:修剪它。事实证明,这在以前建议的解决方案失败的情况下对我有用。

我在评论部分提供了以下技术问题的详细信息。如果细节过多,我道歉。

  • ¿为什么使用命令好看?我明白了here。最初我认为在查看整个文件系统时降低进程优先级会很好。我意识到这对我没有意义,因为我的脚本仅限于几个目录。我将-maxdepth减少到3。
  • ¿为什么要搜索/ home * /?这与此线程无关。我通过源代码编译手动安装所有应用程序与非特权用户(非root用户)。它们安装在“/ home”中。我可以有多个二进制文件和版本一起生活。我需要以主从方式定位所有目录,检查和备份。我可以拥有多个“/ home”(在专用服务器中运行的多个磁盘)。
  • ¿为什么使用-follow?用户可以创建指向目录的符号链接。它的用处取决于,我需要记录找到的绝对路径。

答案 14 :(得分:2)

您可以使用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

应该是魔术

答案 15 :(得分:2)

- =对于MacOS = -

使用别名创建一个新命令:只需添加〜/ .bash_profile行:

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

在新的终端窗口中,您可以调用它:

$ file=<filename or mask>; search
  

例如:

     

$ file = etc;搜索

答案 16 :(得分:0)

如果您使用CSH或TCSH,这是一个解决方案:

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

如果您想要输出到终端:

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

然而,as the "csh-whynot" FAQ describes, you should not use CSH.

答案 17 :(得分:0)

只需使用它来搜索系统中的文件。

find / -name YOUR_SEARCH_TERM 2>&1 | grep YOUR_SEARCH_TERM

我们不要做不必要的工程,你只是想搜索你的文件对吗?如果文件位于您可以访问的区域,那么该命令将为您列出文件。

答案 18 :(得分:-1)

您也可以轻松地将查找结果放入文件中。

找到。 -name&#39; NameOfSearchedFile&#39; &GT;&GT; RESULTS.TXT

答案 19 :(得分:-1)

最小的解决方案就是添加 readable 标志。

find . -name foo -readable