我怎样才能从“查找”中排除所有的“权限被拒绝”信息?

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

find . > files_and_folders 

我正在试验这种信息何时出现。 我需要收集所有不会出现的文件夹和文件。

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

我怎样才能同时隐藏错误?

注意:
*这个答案可能比用例许可证更深,并且find 2>/dev/null在许多情况下可能已经足够了。 对于跨平台的观点以及为了寻求尽可能强大的解决scheme而讨论一些先进的壳技术可能仍然是有意义的,尽pipe防范的情况可能在很大程度上是假设性的。
* 如果您的系统configuration为显示本地化错误消息 ,请在LC_ALL=CLC_ALL=C find ... )前加上find调用的前缀,以确保英文消息被报告,以便grep -v 'Permission denied'按预期工作。 然而,总是显示的任何错误信息都是英文的。

如果你的shell是bash或者zsh ,那么有一个解决scheme比较简单使用符合POSIX标准的find特性 。 而bash本身不是POSIX的一部分,大多数现代化的Unix平台都带有这个平台,使得这个解决scheme具有很高的可移植性:

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

注意: grep的输出可能会 find完成到达,因为整个命令不会等待>(...)的命令完成。 在bash ,你可以通过追加| cat来防止这个 | cat去命令。

  • >(...)是一个很less使用的输出 过程replace ,它允许将输出(在这种情况下, stderr输出( 2> )redirect到>(...)内命令的stdin。
    除了bashzshksh在原理上也支持它们,但是试图将它们与stderr中的redirect结合起来,就像在这里所做的( 2> >(...) ),似乎被默默地忽略了(在ksh 93u+ )。

    • grep -v 'Permission denied'过滤-v )包含短语Permission denied所有行(来自find命令的stderrstream),并将其余的行输出到stderr( >&2 )。

这种做法是:

  • robustgrep仅适用于错误消息 (而不适用于文件path和错误消息的组合,可能导致误报),并且将除权限被拒绝之外的错误消息传递到stderr。

  • 副作用是免费的find的退出代码被保留:无法访问至less一个遇到的文件系统项目结果退出代码1 (虽然这不会告诉你,除了权限被拒绝的错误发生(太) )。


符合POSIX的解决scheme:

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

如果find的输出被反正 (或者完全抑制) 在一个文件中捕获 ,那么来自Jonathan Leffler的答案的基于stream水线的解决scheme是简单的,健壮的和符合POSIX的:

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

请注意,redirect的顺序很重要: 2>&1必须先到达。

先前在文件中捕获stdout输出允许2>&1通过pipe道发送只有错误消息,然后grep可以明确地操作。

唯一的缺点是整体退出代码将是grep命令 ,而不是find的,在这种情况下意味着:如果没有错误或者只有权限被拒绝的错误,则退出代码将是1 (信令失败 ) ,否则(许可被拒绝的错误) 0 – 与意图相反。
也就是说, find退出代码很less使用 ,因为它常常传达的信息超越基本失败,比如传递一条不存在的path。
但是,即使只有一些inputpath由于缺乏权限而无法访问的具体情况反映在find的退出代码中(在GNU和BSD中都find ):如果处理的任何文件发生权限被拒绝的错误,退出代码被设置为1

以下变体解决了以下问题:

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

现在,退出代码指示是否发生 Permission denied 之外的任何错误:如果是,则为0否则为0
换句话说,退出代码现在反映了命令的真实意图:报告成功( 0 ),如果完全没有错误或发生权限被拒绝的错误。
这可能比通过传递find的退出代码更好,就像顶层的解决scheme一样。


评论中的gniourf_gniourf提出了一种使用复杂redirect的解决scheme (仍然符合POSIX标准), 即使将文件path打印到标准输出的默认行为也是如此

 { find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1 

简而言之:自定义文件描述符3用于临时交换stdout( 1 )和stderr( 2 ),以便单独的错误消息可以通过标准输出传递给grep

如果没有这些redirect,数据(文件path) 错误消息将通过标准输出( grep通过grep ,并且grep将无法区分错误消息 Permission denied错误消息 Permission denied和一个名称恰好包含短语Permission denied

然而,在第一个解决scheme中,所报告的退出代码将是grep的,没有find ,但是可以应用与上面相同的修复。


关于现有答案的说明:

  • find . ! -readable -prune -o -print 迈克尔布鲁克斯的答案有几点需要注意find . ! -readable -prune -o -print find . ! -readable -prune -o -print find . ! -readable -prune -o -print

    • 它需要GNU find ; 值得注意的是,它不能在macOS上工作。 当然,如果你只需要使用GNU find的命令,这对你来说不会有问题。

    • 一些Permission denied错误仍然可能会出现: find ! -readable -prune find ! -readable -prune报告当前用户具有权限但缺lessx (可执行)权限的子目录的这些错误。 原因是因为目录本身可读的, -prune没有被执行,并且试图进入该目录然后触发错误消息。 这就是说, 典型的情况是,许可证丢失了。

    • 注意:以下几点是关于哲学和/或具体用例的问题,您可能会认为它与您无关,而且该命令可以很好地满足您的需求,特别是如果只是简单地打印path,那么您只需:

      • 如果您将权限被拒绝的错误消息的过滤概念化为您希望能够应用于任何 find命令的单独任务,那么主动防止权限被拒绝的错误的相反方法需要在find命令中引入“噪声”也引入了复杂性和逻辑错误
      • 例如,对Michael的回答(截至撰写本文时)的最新评论意见试图展示如何通过包含一个名称filter来扩展命令,如下所示:
        find . ! -readable -prune -o -name '*.txt'
        但是,这样做不能按预期工作,因为尾部-print操作是必需的 (可以在这个答案中find解释)。 这种微妙的东西可能会引入错误。
  • 乔纳森·莱弗勒的答案中的第一个解决scheme, find . 2>/dev/null > files_and_folders find . 2>/dev/null > files_and_folders ,正如他自己所说的那样, 盲目地将所有的错误消息都保持沉默 (并且解决方法繁琐而且不完全健壮,正如他也解释的那样)。 然而,从语用上讲 ,这是最简单的解决scheme ,因为您可能满意地认为任何和所有的错误都是与权限相关的。

  • 薄雾的答案 , sudo find . > files_and_folders sudo find . > files_and_folders简洁而实用,但是除了打印文件名之外的其他内容都是不明智的 ,出于安全原因:因为你是以root用户身份运行的,“你可能会冒着整个系统被查找或一个恶意的版本,或者一个不正确的调用,意想不到的写入,如果你用普通的权限运行,这是不会发生的“(来自thinee对tripleee的回应)。

  • 在viraptor的答案中的第二个解决scheme, find . 2>&1 | grep -v 'Permission denied' > some_file find . 2>&1 | grep -v 'Permission denied' > some_file find . 2>&1 | grep -v 'Permission denied' > some_file存在误报风险(由于通过pipe道发送stdout和stderr混合),而不是通过stderr报告许可拒绝错误,而是捕获它们输出文件中的输出path。

使用:

 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命令上的I / Oredirect是: 2>&1 > files_and_folders | 。 pipe道将标准输出redirect到grep命令并首先应用。 2>&1将标准错误发送到标准输出(pipe道)的相同位置。 > files_and_folders将标准输出(但不是标准错误)发送到文件。 最终的结果是,写入标准错误的消息被发送到pipe道, find的常规输出被写入文件。 grep过滤标准输出(你可以决定你想要的select是多么的有select性,而且可能需要改变locale和O / S的拼写),最后>&2意味着存在的错误信息(写入标准输出)再次转到标准错误。 最终的redirect在terminal上可以被认为是可选的,但是在脚本中使用它是一个非常好的主意,这样错误消息就会出现在标准错误上。

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

如果您希望适应系统中特定版本的find ,则可能有其他select。 特别是GNU find在其他版本中有很多选项不可用 – 请参阅当前接受的一个选项集。

使用:

 find . ! -readable -prune -o -print 

或更一般地说

 find <paths> ! -readable -prune -o <other conditions like -name> -print 
  • 避免“权限被拒绝”
  • 并且不要压制(其他)错误信息
  • 并获得退出状态0(“所有文件处理成功”)

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

  • -readabletesting匹配可读文件。 那! 当testing为false时,运算符返回true。 而! -readable ! -readable匹配不可读的目录(&文件)。
  • -prune动作不会进入目录。
  • ! -readable -prune ! -readable -prune可以被翻译为:如果目录不可读,请不要下载到它。
  • -readabletesting考虑到了-permtesting忽略的访问控制列表和其他许可权文物。

有关更多详细信息,另请参阅find(1)手册页。

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

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

这是因为许可。 要解决这个问题:

  1. 你可以使用sudo命令: sudo find /. -name 'toBeSearched.file' sudo find /. -name 'toBeSearched.file' 。 它要求超级用户的密码,当input密码时,你会看到你真正想要的结果。

  2. 您可以使用(一般显示/屏幕)将标准错误输出redirect到某个文件,并避免在屏幕上看到错误信息! redirect到一个特殊的文件/ dev / null:

     find /. -name 'toBeSearched.file' 2>/dev/null 
  3. 您可以使用(一般显示/屏幕)将标准错误输出redirect到标准输出(一般显示/屏幕),然后使用带-v“invert”参数的grep命令进行pipe道输出,以便不会看到“权限被拒绝”字对:

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

我不得不使用:

 find / -name expect 2>/dev/null 

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

期望成为我正在寻找的期望程序的位置。

通过使用2> / dev / null将 stderr/ dev / null

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

您也可以使用-perm-prune谓词来避免降序到不可读的目录中(另请参见如何从find程序中删除“permission denied”打印输出语句 – Unix&Linux Stack Exchange ):

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

redirect标准错误。 例如,如果你在unix机器上使用bash,你可以像这样将标准错误redirect到/ 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$ find . -type f -name "your_pattern" -exec du -ch {} + 2>/dev/null | grep total$

这将返回给定模式的文件的总大小。 注意find命令结尾的2>/dev/null

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

 find . 2>/dev/null > some_file 

或者先joinstderr和stdout,然后grep out这些特定的错误:

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

简单的回答:

find . > files_and_folders 2>&-

2>&-closures( - )标准错误文件描述符( 2 ),这样所有的错误信息都是静音的。

  • 如果任何“ Permission denied ”错误将被打印,退出代码将仍然是1

GNU find可靠答案:

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

传递额外的选项来find -prune (防止下降到),但仍然-print不具有( \! )同时具有-readable-executable权限的任何目录( -type d ),或者( -o ) – -print任何其他文件。

  • -readable-executable选项是GNU扩展,而不是POSIX标准的一部分
  • 可能还会在exception/损坏的文件上返回“ Permission denied ”(例如,使用lxcfs <v2.0.5查看影响容器挂载文件系统的bug报告 )

强大的答案适用于任何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

使用pipe道将标准错误stream传递给grep ,删除包含'Permission denied'string的所有行。

LC_ALL=C使用环境variables 3>&2 2>&1 1>&33>&2 2>&1 重复文件描述符来设置POSIX语言 环境 ,以将标准错误streampipe道grep[ $? = 1 ] [ $? = 1 ]使用[]来反转由grep返回的错误代码,以近似find的原始行为。

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

为了避免权限被拒绝的警告,告诉find通过从search中删除它们来忽略不可读的文件。 将expression式作为OR添加到查找中,例如

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

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

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

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

所以(从列表中匹配不可读的文件和修剪) OR (匹配path/ dev和prune从列表)(匹配文件如 * .jbd 并显示它)

使用

 sudo find / -name file.txt 

这是愚蠢的(因为你提升search)和不安全的,但写得更短。

你可以使用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脚本中使用命令查找来查找一些目录,然后检查它们的内容。 我使用退出代码评估命令查找成功:值为零,否则失败。

Michael Brux 上面提供的答案有时是有效的。 但是我有一个失败的场景! 我发现了这个问题,并且自己修复了它。 我需要修剪文件时:

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

看到这里的关键问题是:和/或。 我读的一个很好的build议条件序列是:

 -type d ! -readable ! -executable -prune 

这不总是工作。 这意味着在匹配时会触发修剪:

 it is directory AND no read access AND no execute access 

当读访问被授权但是没有执行访问时,这个expression序列失败。

经过一些testing,我意识到这一点,并改变我的shell脚本解决scheme:

很好找/ home * / -maxdepth 5 – 关注\
\( -type d -a !\(-readable -a -executable \) \) -prune \
-o \
\(-type d -a -readable -a -executable -a -name“$ {m_find_name}”\)-print

这里的关键是把“不正确的”放在一个组合的expression式上:

 has read access AND has execute access 

否则,它没有完全访问,这意味着:修剪它。 这在以前build议的解决scheme失败的情况下certificate对我有用。

我在评论部分提供了以下技术细节。 如果细节过多,我很抱歉。

  • ¿为什么使用命令很好? 我在这里得到了主意。 起初,我认为在查看整个文件系统时降低进程优先级是很好的做法。 我意识到这对我来说毫无意义,因为我的脚本只限于几个目录。 我把-maxdepth减less到了3。
  • ¿为什么在/ home / /中search? 这与这个线程无关。 我手动安装所有的应用程序通过源代码编译与非特权用户(而不是根)。 它们安装在“/ home”中。 我可以有多个二进制文件和版本一起生活。 我需要find所有的目录,检查并以主从方式备份。 我可以有多个“/ home”(多个磁盘在专用服务器中运行)。
  • ¿为什么使用 – 关注? 用户可能会创build符号链接到目录。 这是有用的,我需要logging下find的绝对path。

– =对于MacOS = –

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

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

并在新的terminal窗口中可以调用它:

 $ file=<filename or mask>; search 

例如:

$ file = etc; search

你也是一个简单的解决scheme,把你的查找结果放在一个文件中。

找 。 -name'NameOfSearchedFile'>> results.txt