【问题标题】:How can I exclude all "permission denied" messages from "find"?如何从“查找”中排除所有“权限被拒绝”消息?
【发布时间】:2024-01-16 23:12:01
【问题描述】:

我需要隐藏所有 permission denied 消息:

find . > files_and_folders

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

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

如何同时隐藏错误?

【问题讨论】:

  • 好问题!不幸的是,前三个答案根本不适用于 Debian Linux。或者至少我的配置。我需要 Fatih 的解决方案,find /. -name 'toBeSearched.file' 2>/dev/null

标签: bash error-handling find file-permissions


【解决方案1】:

用途:

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 过滤标准输出(您可以决定您希望它的选择性,并且可能必须根据语言环境和 O/S 更改拼写),最后的 >&2 意味着幸存的错误消息(写入标准输出)再次进入标准错误。最终的重定向在终端可以被认为是可选的,但是在脚本中使用它是一个非常好的主意,这样错误消息就会出现在标准错误上。

这个主题有无穷无尽的变化,这取决于你想做什么。这将适用于具有任何 Bourne shell 衍生工具(Bash、Korn 等)的任何 Unix 变体以及任何符合 POSIX 的find 版本。

如果您希望适应系统上的特定版本的find,可能有其他可用选项。尤其是 GNU find 有无数其他版本中没有的选项 - 请参阅当前接受的一组选项的答案。

【讨论】:

  • 如果你和我一样,请注意空间不足很重要! 2>/dev/null,没有空格!
  • 2> 是一个没有任何空格的单元;你可以在它和文件名之间有一个空格。与其他重定向类似,例如2>&1(将标准错误重定向到与标准输出相同的位置),或2>&-,关闭标准错误等。有关其余血腥细节,请参见Redirections。 (上面的代码是通用的类似 POSIX 的 shell,不特定于 bash。)
  • 这是一个可接受的解决方案吗? 1)您将所有错误重定向到 dev/null 2)您正在过滤显式错误字符串!取决于这些是众所周知的脆弱,如果您的文件位于名为“权限被拒绝”的目录中怎么办?糟糕!
  • @Gunchars:您提出的观点已包含在答案中 - 或者明确的错误字符串已包含在问题的规范中。第一个命令确实将所有错误发送到/dev/null;第二个没有。答案提到了假设您没有任何名为permission denied 的文件。所以,我不清楚你真正反对什么。
  • 我反对使用 grepping 错误字符串来修改程序的输出。它在大多数情况下都可以工作,但简单不是正确的解决方案(在下面找到 perms)。举个例子,为什么这在 OSX 上不起作用,因为错误是“权限被拒绝”。对于错误字符串中甚至存在微小差异的任何其他系统也是如此(国际化任何人?)
【解决方案2】:

重定向标准错误。例如,如果您在 unix 机器上使用 bash,您可以像这样将标准错误重定向到 /dev/null:

find . 2>/dev/null >files_and_folders

【讨论】:

    【解决方案3】:

    使用 2>/dev/null

    stderr 连接到 /dev/null

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

    【讨论】:

    • 即使在 Mac OSX 上也能正常工作。甚至find . -name '...' -print 2>/dev/null
    【解决方案4】:

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

    find . 2>/dev/null > some_file
    

    或者先加入stderr和stdout,然后grep出那些具体的错误:

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

    【讨论】:

      【解决方案5】:

      我不得不使用:

      find / -name expect 2>/dev/null
      

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

      expect 是我正在搜索的期望程序的位置。

      【讨论】:

      • @Masi,答案中的命令不使用expect。相反,expect 只是此命令将尝试查找的文件的名称。
      • 盲目地重定向所有 stderr 输出只是为了忽略一类错误消息通常是一个坏主意 - 您将在此过程中丢失所有其他任意错误。
      【解决方案6】:

      如果您想从根目录 "/" 开始搜索,您可能会看到如下输出:

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

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

      1. 你可以使用 sudo 命令:

        sudo find /. -name 'toBeSearched.file'
        

      它询问超级用户的密码,当输入密码你会看到你真正想要的结果。如果您没有使用 sudo 命令的权限,即您没有超级用户的密码,请先让系统管理员将您添加到 sudoers 文件中。

      1. 您可以使用将标准错误输出从(通常显示/屏幕)重定向到某个文件,避免在屏幕上看到错误消息!重定向到特殊文件 /dev/null :

        find /. -name 'toBeSearched.file' 2>/dev/null
        
      2. 您可以使用将标准错误输出从(通常显示/屏幕)重定向到标准输出(通常显示/屏幕),然后使用带有 -v "invert" 参数的 grep 命令进行管道传输,以不查看具有 ' 的输出行Permission denied' 词对:

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

      【讨论】:

      • @scottmrogowski 除了它没有回答问题... 1. 要求系统管理员将您添加到 sudoers 文件中。 2.sudo find...
      • 正是我想要的!
      • 在阅读了四个高票数、一页长的答案全部不正确后,我已经有一段时间没有找到正确的答案了。谢谢!
      【解决方案7】:

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

      【讨论】:

      • -perm -g+r,u+r,o+r 仅匹配为所有 3 个 文件的安全主体设置了r(读取)权限的文件,这与 文件的安全主体是否具有直接关系。 i>当前用户是否可以读取该文件。它可能会丢失当前用户可以读取的文件和匹配他们不能读取的文件。
      • 我认为find . -type d ! \( -perm -u+r -o -perm -g+r -o -perm -o+r \) -prune -o -print 会是一个很好的解决方案。
      • @Mattia72:不,用-perm 完全模拟-readable 基本上是不可能的 - 请参阅我之前的评论并考虑这个例子:echo 'hi' > file; sudo chown nobody:nobody file; sudo chmod o-r file; find file -perm -u=r 打印file,因为它的用户读取位已设置,但它与nobody 用户相关,而不是当前用户。当前用户无法读取该文件;试试cat file。另请参阅:我的this answer
      【解决方案8】:

      用途:

      find . ! -readable -prune -o -print
      

      或更一般地

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

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

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

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

      【讨论】:

      • 已经提到了差异。如果您不明白,那么答案可能对您没有任何影响? STDOUT 是一样的 - STDERR 是不同的(你会得到这个答案的其他错误消息) - $?是不同的(这个答案是 0“成功”,当没有其他错误发生时 - 重定向到 dev/null 时总是 > 0“不成功”) - 也许有人需要“正确” $?在脚本中
      • @Masi 最明显的缺陷是乔纳森的回答(grep -v) 将排除包含“权限被拒绝”的文件名:)
      • 我觉得这里加个比较合适,如果需要加一些其他的搜索条件,应该用-o:find . ! -readable -prune -o -name '*.txt'
      • 请注意,POSIX find 不包括 -readable 作为选项; find 也没有用于 BSD 和 Mac OS X(我不确定其他系统)。所以,如果你有 GNU find 保证,这很好用,但如果你不能保证系统安装了 GNU find,那么如何调整它就不清楚了。 (它可以在 Linux 上正常工作;它可能会或可能不会在其他地方工作。)
      • find . ! -readable -prune -o -name '*.txt' 似乎无法使用 find 4.2.2 在 Ubuntu 14.04 上运行。似乎忽略了-name。出于某种奇怪的原因,我在find . \( ! -readable -prune \) -o -name '*.txt' -print 上取得了成功
      【解决方案9】:

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

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

      这主要是说 (匹配一个不可读的文件并将其从列表中删除)(匹配一个类似的名称 *.jbd 并显示它 [with ls])。 (请记住,默认情况下,除非您使用 -or,否则表达式是 AND 一起使用的。)您需要在第二个表达式中使用 -ls,否则 find 可能会添加一个默认操作来显示任一匹配项,这也会显示所有不可读的文件.

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

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

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

      【讨论】:

        【解决方案10】:

        使用

        sudo find / -name file.txt
        

        这是愚蠢的(因为你提升了搜索)并且不安全,但写起来要短得多。

        【讨论】:

        • 您在这里搜索整个文件系统,因此您的意思是“提升搜索”。为什么说它不安全?因为它正在搜索整个文件系统?
        • 因为 sudo 以 root 权限运行 find 命令,这基本上是个坏主意。违反了隔离和最小特权原则。
        • 这里的“提升”是root权限,sudo。您的整个系统可能会被find 中的错误或恶意版本或错误调用导致意外写入某些内容而搞砸,如果您以正常权限运行此操作,则不会发生这种情况。
        【解决方案11】:

        虽然上述方法不能解决 Mac OS X 的情况,因为 Mac OS X 不支持 -readable 开关,但这是您可以避免输出中出现“权限被拒绝”错误的方法。这可能会对某人有所帮助。

        find / -type f -name "your_pattern" 2&gt;/dev/null

        如果您正在使用带有find 的其他命令,例如,在2&gt;/dev/null 目录中查找特定模式的文件大小,仍将如下所示。

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

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

        【讨论】:

        • 很好地绑定到 OS X!乔纳森的回答解释了2&gt;/dev/null 部分。你能解释一下-exec du -ch {} + 2&gt;/dev/null | grep total$的部分吗?
        • @Masi 您可以使用任何带有-exec 选项的命令对find 命令找到的文件或目录执行进一步操作。 du -ch file_pattern 计算与file_pattern 匹配的每个文件的大小,该输出的最后一行是与file_pattern 匹配的所有文件的总和。请参阅du 的手册页。 grep total 只过滤提取总计的行(即最后一行)。
        【解决方案12】:

        注意:

        • 这个答案可能比用例保证的更深入,并且 find 2&gt;/dev/null 在许多情况下可能已经足够好了。从跨平台的角度来看,它可能仍然对一些先进的 shell 技术的讨论感兴趣,以便找到一个尽可能健壮的解决方案,即使所防范的情况可能在很大程度上是假设性的。

        如果您的shell 是bashzsh,则有一个解决方案既可靠又相当简单,只使用符合POSIX 的@987654333 @特征;虽然bash 本身不是 POSIX 的一部分,但大多数现代 Unix 平台都附带它,这使得该解决方案具有广泛的可移植性:

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

        注意:

        • 如果您的系统配置为显示本地化错误消息,请在下面的 find 调用前加上 LC_ALL=C (LC_ALL=C find ...) 以确保 报告英文消息,以便grep -v 'Permission denied' 按预期工作。但是,确实显示的任何错误消息都将始终以英文显示。

        • &gt;(...) 是一个(很少使用)输出 process substitution,它允许将输出(在这种情况下,stderr 输出 (2&gt;) 重定向到&gt;(...).
          里面的命令 除了bashzshksh 原则上也支持它们,但尝试将它们与来自stderr 的重定向结合起来,就像这里所做的那样( 2&gt; &gt;(...)),似乎被默默地忽略了(在 ksh 93u+ 中)。

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

          • 注意:grep 的某些输出可能会在find 完成后到达,因为整个命令不会等待&gt;(...) 内的命令完成.在bash 中,您可以通过将| cat 附加到命令来防止这种情况发生。

        这种方法是:

        • 稳健grep 仅适用于错误消息(而不适用于文件路径和错误消息的组合,可能导致误报)和错误除了权限被拒绝的消息之外的消息被传递到 stderr。

        • 无副作用find 的退出代码被保留:无法访问遇到的至少一个文件系统项导致退出代码 1(尽管这不会告诉你除了权限被拒绝的错误其他是否发生过(也))。


        符合 POSIX 的解决方案:

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

        如果find 的输出无论如何要在文件 中捕获(或完全抑制),那么Jonathan Leffler's answer 的基于管道的解决方案很简单、健壮且符合 POSIX:

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

        注意重定向的顺序很重要:2&gt;&amp;1 必须在前

        在文件中预先捕获标准输出允许2&gt;&amp;1 通过管道发送错误消息,然后grep 可以明确地对其进行操作。

        唯一的缺点是整个退出代码将是 grep 命令的,而不是 find 的,在这种情况下意味着:如果有没有个错误或只有个权限被拒绝的错误,退出代码将是1(信号失败),否则(错误不是权限被拒绝的那些)0 - 这与意图相反。
        也就是说,find 的退出代码无论如何都很少使用,因为它通常传达的信息很少em>根本性故障,例如通过不存在的路径。
        但是,由于缺少权限,甚至只有 一些 输入路径无法访问的特定情况 反映在 find 的退出代码中(在 GNU 和 BSD 中) find):如果处理的任何文件发生权限被拒绝错误,则退出代码设置为1

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

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

        现在,退出代码指示是否有任何错误除了 Permission denied 发生:1 如果是,0 否则。
        换句话说:退出代码现在反映了命令的真实意图:如果完全没有错误或发生权限被拒绝的错误,则会报告成功 (0)。
        可以说,这甚至比仅传递 find 的退出代码更好,就像顶部的解决方案一样。


        gniourf_gniourf 在 cmets 中提出了一个(仍然符合 POSIX)使用复杂重定向对这个解决方案进行概括,它即使在将文件路径打印到 标准输出

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

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

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

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


        现有答案的注释:

        • Michael Brux's answerfind . ! -readable -prune -o -print有几点需要注意:

          • 它需要 GNU find;值得注意的是,它不适用于 macOS。当然,如果您只需要使用 GNU find 的命令,这对您来说不是问题。

          • 一些Permission denied 错误可能仍然浮出水面:find ! -readable -prune 报告当前用户确实拥有r 权限的目录的 项的此类错误,但缺少x(可执行)权限。原因是因为目录本身可读的,-prune 没有被执行,然后尝试下降进入那个目录会触发错误消息。也就是说,典型情况是缺少r 权限。

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

            • 如果您将权限拒绝错误消息的过滤概念化为单独的任务,您希望能够将其应用于任何find命令,那么主动防止权限被拒绝错误的相反方法需要在find命令中引入“噪音”,这也引入了复杂性和逻辑缺陷。
            • 例如,对 Michael 的回答(截至撰写本文时)投票最多的评论试图通过包含 -name 过滤器来显示如何扩展命令,如下所示:
              find . ! -readable -prune -o -name '*.txt'
              然而,这没有按预期工作,因为尾随的-print 操作是必需的(可以在this answer 中找到解释)。这种微妙之处可能会引入错误。
        • Jonathan Leffler's answerfind . 2&gt;/dev/null &gt; files_and_folders 中的第一个解决方案,正如他自己所说,盲目地使所有错误消息静音(解决方法很麻烦,而且不完全健壮,正如他也解释的那样)。 务实地说,但是,它是最简单的解决方案,因为您可能满足于假设所有错误都与权限相关。

        • mist's answer, sudo find . &gt; files_and_folders, 简洁而实用,但出于安全原因,除了打印文件名之外的任何事情都是不明智的:因为你是以 root 用户身份运行,“您可能会冒着整个系统被 find 中的错误或恶意版本或错误调用导致意外写入某些内容的风险,如果您运行此程序就不会发生这种情况具有正常权限”(来自 tripleee 对雾的回答的评论)。

        • viraptor's answerfind . 2&gt;&amp;1 | grep -v 'Permission denied' &gt; some_file 中的第二个解决方案存在误报的风险(由于通过管道发送 stdout 和 stderr 的混合),并且可能不会报告 -permission-denied 错误通过 stderr,将它们与输出文件中的输出路径一起捕获。

        【讨论】:

        • 问一个简单的问题:为什么要使用进程替换而不仅仅是管道:find . 2&gt;&amp;1 &gt; files_and_folders | grep -v 'Permission denied' &gt;&amp;2?
        • @LéoLéopoldHertz준영:如果你不想输出到外部文件,那就做更多的管道:{ find . 3&gt;&amp;2 2&gt;&amp;1 1&gt;&amp;3 | grep -v 'Permission denied' &gt;&amp;3; } 3&gt;&amp;2 2&gt;&amp;1
        • @LéoLéopoldHertz준영:只是它符合 POSIX。进程替换 &gt;(...) 是特定于 Bash 的。
        • 我不确定是否应该强调和宣传 find 的退出代码的保留:find 的退出代码是出了名的无用。在这里,它很可能会不为零(而且毫无用处)。
        • POSIX 明确要求 execute/search 文件模式权限才能“搜索”目录(检索包含文件的 inode)。 find 这样做是为了进入子目录(除了需要read 权限来列出目录中的文件)。这不是“错误”或“移植错误”。
        【解决方案13】:

        以上答案都不适合我。我在 Internet 上找到的所有内容都集中在:隐藏错误。 None 正确处理进程返回代码/退出代码。我在 bash 脚本中使用命令 find 来定位一些目录,然后检查它们的内容。我使用退出代码评估命令 find 是否成功:值为零有效,否则失败。

        Michael Bruxanswer provided above 有时会起作用。但我有一个失败的场景!我发现了问题并自己解决了。我需要在以下情况下修剪文件:

        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 脚本解决方案更改为:

        很好地找到 /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
        

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

        我提供以下有关 cmets 部分问题的技术细节。如果细节过多,我深表歉意。

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

        【讨论】:

        • 感谢您的回答和精彩的观察!我在这里开了一个赏金来更好地预览你的答案。我认为这是一个很好的发现,不会阻止读取和执行访问。 - - 你能解释一下你为什么使用nicefind $HOME -maxdepth 5 -follow ...吗?
        • 所述的shell脚本不是通用的(只列出与${m_find_name}匹配的目录),并且包含几个与问题无关的选项(nice/home*-maxdepth 5-follow)。我添加了一个答案,以更简洁地解决“过滤可读但不可执行的目录”的具体问题,同时保持通用性。
        【解决方案14】:

        简单回答:

        find . &gt; files_and_folders 2&gt;&amp;-

        2&gt;&amp;- 关闭 (-) 标准错误文件描述符 (2),因此所有错误消息都被静音。

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

        GNU find 的可靠答案:

        find . -type d \! \( -readable -executable \) -prune -print -o -print &gt; files_and_folders

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

        适用于任何 POSIX 兼容 find(GNU、OSX/BSD 等)的可靠答案

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

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

        LC_ALL=C 使用environment variable3&gt;&amp;2 2&gt;&amp;1 1&gt;&amp;33&gt;&amp;2 2&gt;&amp;1 duplicate file descriptors 设置POSIX locale 以将标准错误流通过管道传送到grep,而[ $? = 1 ] 使用[]grep 返回的错误代码反转为近似find 的原始行为。

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

        【讨论】:

        • 您如何看待 JordiFerran 的回答建议? - - 你能比较一下你的答案吗?
        • 上述答案的 shell 脚本不是通用的(仅列出与 ${m_find_name} 匹配的目录),并且包含几个与问题无关的选项(nice、/home*、-maxdepth 5、 -跟随)。这个答案更简洁地解决了“过滤可读但不可执行的目录”的具体问题,同时保持通用性。
        • @wjordan:谢谢。我删除了我的 cmets,但有一点仍然适用:基于 -perm 的解决方案不值得介绍,因为它比引用所暗示的更根本地做了一些与预期不同的事情:它纯粹是file-centric 测试,与 file's 的所有者和组有关,它们都与调用命令的用户没有任何保证关系(参见我的this answer。看起来就像您修改后的 GNU 解决方案一样,现在不会捕获源自 files 的权限被拒绝错误。
        • 我不认识你正在使用的语法(既不是 GNU 也不是 BSD),但让我用一个独立的例子来说明我的观点:echo 'hi' &gt; file; sudo chown nobody:nobody file; sudo chmod o-r file; find file -perm -u=r 打印 file,因为它的用户读取位已设置,但它与nobody 用户相关,而不是当前用户。当前用户无法读取该文件;试试cat file
        • @mklement0 感谢您的讨论,我设法产生了您在另一个测试中描述的行为(不知道我第一次做错了什么),似乎-perm 没有用于确定用户当前的权限。从这个答案中删除了那个替代方案。
        【解决方案15】:

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

        应该是魔法

        【讨论】:

          【解决方案16】:

          -=MacOS=-

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

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

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

          $ file=<filename or mask>; search
          

          例如:

          $ 文件=等;搜索

          【讨论】:

            【解决方案17】:

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

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

            如果你想输出到终端:

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

            但是,as the "csh-whynot" FAQ describes, you should not use CSH.

            【讨论】:

            • 我想 grep 所有 txt 文件并排除隐藏文件/目录,省略要打印的“权限被拒绝”消息。我正在使用 csh 外壳。我使用了以下命令,但它们无法正常工作 find 。 -type f -iname ".txt" -not -path '*/\.' | egrep -v“权限被拒绝”查找。 -type f -iname ".txt" -not -path '*/\.' 2>/dev/null 出现以下错误。 find:路径必须在表达式之前:2 用法:find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [表达式]
            【解决方案18】:

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

            find / -name YOUR_SEARCH_TERM 2&gt;&amp;1 | grep YOUR_SEARCH_TERM

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

            【讨论】:

              【解决方案19】:

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

              find . -name foo -readable

              【讨论】:

                【解决方案20】:

                为 GNU find 优化的解决方案

                至少对于某些系统+文件系统组合,find 不需要stat 文件来获取其类型。然后你可以在测试可读性之前检查它是否是一个目录,以加快搜索速度——我在我所做的测试中得到了大约 30% 的改进。因此,对于长时间搜索或运行频率足够高的搜索,请使用以下其中一种:

                打印所有可见的内容

                $ find . -print -type d ! -readable -prune
                $ find . -type d ! -readable -prune , [expression] -print
                

                打印可见的文件

                $ find . -type d \( ! -readable -prune -o -true \) -o [expression] -print
                

                打印可见目录

                $ find . -type d -print ! -readable -prune
                $ find . -type d \( ! -readable -prune , [expression] -print \)
                

                仅打印可读目录

                $ find . -type d ! -readable -prune -o [expression] -print
                

                注意事项

                -readable,(逗号)运算符是 GNU 扩展。这个表达式

                $ find . [expression] , [expression]
                

                逻辑上等价

                $ find . \( [expression] -o -true \) [expression]
                

                这是因为启用此优化的find 实现将在讨论的用例中完全避免stating 非目录文件。


                编辑:shell 函数

                这是我最终使用的 POSIX shell 函数,用于将此测试添加到任何表达式。隐式 -print 和命令行选项似乎可以正常工作:

                findr () {
                    j=$#; done=
                    while [ $j -gt 0 ]; do
                        j=$(($j - 1))
                        arg="$1"; shift
                        test "$done" || case "$arg" in
                            -[A-Z]*) ;;  # skip options
                            -*|\(|!)     # find start of expression
                                set -- "$@" \( -type d ! -readable -prune -o -true \)
                                done=true
                                ;;
                        esac
                        set -- "$@" "$arg"
                    done
                    find "$@"
                }
                

                答案中列出的其他两个替代方案导致 POSIX shell 中的语法错误(甚至无法获取包含函数定义的文件)或 ZSH 中的错误输出......运行时间似乎是相同的。

                【讨论】: