首页 文章

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

提问于
浏览
713

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

find . > files_and_folders

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

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

如何同时隐藏错误?

18 回答

  • -1

    我不得不使用:

    find / -name expect 2>/dev/null
    

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

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

  • 510

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

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

  • 4

    使用 2>/dev/null 管道 stderr/dev/null

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

  • 107

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

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

    很好找/ home * / -maxdepth 5 -follow \ \(-type d -a!\(-readable -a -executable \)\)-prune \ -o \ \(-type d -a -readable -a -executable -a -name“$ ”\“ - print

    这里的关键是为组合表达式放置“not true”:

    has read access AND has execute access
    

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

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

    • ¿为什么使用命令好?我明白了here . 最初我认为在查看整个文件系统时降低进程优先级会很好 . 我意识到这对我来说没有意义,因为我的脚本仅限于几个目录 . 我将-maxdepth减少到3 .

    • ¿为什么要搜索/ home * /?这与此线程无关 . 我通过源代码编译手动安装所有应用程序与非特权用户(非root用户) . 它们安装在"/home"内 . 我可以有多个二进制文件和版本一起生活 . 我需要以主从方式定位所有目录,检查和备份 . 我可以有多个"/home"(在专用服务器中运行的几个磁盘) .

    • ¿为什么要使用-follow?用户可以创建指向目录的符号链接 . 它的用处取决于,我需要记录所发现的绝对路径 .

  • 2

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

    如果 shell is bash or zsh ,那么 a solution that is robust while being reasonably simple ,使用 only POSIX-compliant find features ;虽然 bash 本身不是POSIX的一部分,但大多数现代Unix平台都附带它,使这个解决方案具有广泛的可移植性:

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

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

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

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

    这种方法是:

    • robustgrep 仅应用于错误消息(而不是文件路径和错误消息的组合,可能导致误报),并且除了权限拒绝之外的错误消息将传递给stderr .

    • side-effect freefind 的退出代码被保留:无法访问至少一个遇到的文件系统项导致退出代码 1 (尽管这不会告诉您是否也发生了除权限拒绝之外的错误) .


    符合POSIX标准的解决方案:

    完全符合POSIX标准的解决方案有限制或需要额外的工作 .

    If find's output is to be captured in a file anyway (或完全被压制),然后来自Jonathan Leffler's answer的基于管道的解决方案简单,强大且符合POSIX:

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

    请注意,重定向的顺序很重要: 2>&1 必须先到 .

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

    only downside is that the overall exit code will be the grep command's ,而不是 find ,在这种情况下意味着:如果根本没有错误或只有权限拒绝错误,退出代码将是 1 (信号失败),否则(除了权限被拒绝的错误) 0 - 这与意图相反 .
    That said, find's exit code is rarely used anyway ,因为它经常传达除了基本失败之外的一些信息,例如传递一条不存在的路径 .
    但是,由于缺少权限,甚至只有部分输入路径无法访问的特定情况反映在 find 的退出代码中(在GNU和BSD _249065中):如果处理的任何文件发生权限被拒绝错误,退出代码设置为 1 .

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

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

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


    gniourf_gniourf在评论中提出了一个(仍然符合POSIX) generalization of this solution using sophisticated redirections ,其中 works even with the default behavior of printing the file paths to stdout

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

    简而言之:自定义文件描述符 3 用于临时交换stdout( 1 )和stderr( 2 ),因此只能通过stdout将错误消息传送到 grep .

    如果没有这些重定向,数据(文件路径)和错误消息都将通过stdout传送到 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 命令中引入"noise",这也是介绍了复杂性和逻辑缺陷 .

    • 例如,对迈克尔答案的最高投票评论(截至本文撰写时)试图通过包括一个来扩展命令 -name 过滤器,如下:
      find . ! -readable -prune -o -name '*.txt'
      但是,这不能按预期工作,因为需要尾随 -print 操作(可以在this answer中找到解释) . 这种微妙之处可能会引入错误 .

    • Jonathan Leffler's answerfind . 2>/dev/null > files_and_folders 中的第一个解决方案,正如他自己所述, blindly silences all error messages (并且解决方法很麻烦且不完全健壮,正如他也解释的那样) . Pragmatically speaking ,但是,它是 simplest solution ,因为您可能会满足于假设任何和所有错误都与权限相关 .

    • mist's answersudo find . > files_and_foldersis concise and pragmatic, but ill-advised for anything other than merely printing filenames ,出于安全原因:因为您以root用户身份运行,"you risk having your whole system being messed up by a bug in find or a malicious version, or an incorrect invocation which writes something unexpectedly, which could not happen if you ran this with normal privileges"(来自tripleee对雾的回答的评论) .

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

  • 0

    使用

    sudo find / -name file.txt
    

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

  • 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.

  • 29

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

    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
    
    • 您可以使用标准错误输出从(通常显示/屏幕)重定向到标准输出(通常显示/屏幕),然后使用带有-v“invert”参数的grep命令管道,以便不查看具有'权限被拒绝的输出行'单词对:
    find /. -name 'toBeSearched.file' 2>&1 | grep -v 'Permission denied'
    
  • 2

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

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

    应该是神奇的

  • 51

    虽然上述方法无法解决Mac OS X的问题,因为Mac OS X不支持 -readable 开关,但这是您可以避免输出中的'Permission denied'错误的方法 . 这可能对某人有帮助 .

    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命令末尾的 2>/dev/null .

  • 10

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

    find . 2>/dev/null >files_and_folders
    
  • 13
    • =对于MacOS = -

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

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

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

    $ file=<filename or mask>; search
    

    例如:$ file = etc;搜索

  • 23

    使用:

    find . ! -readable -prune -o -print
    

    或更一般地说

    find <paths> ! -readable -prune -o <other conditions like -name> -print
    
    • 以避免"Permission denied"

    • 并且不要抑制(其他)错误消息

    • 并退出状态0("all files are processed successfully")

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

    • -readable 测试匹配可读文件 . 当test为false时, ! 运算符返回true . 并且 ! -readable 匹配不可读的目录(&files) .

    • -prune 操作不会进入目录 .

    • ! -readable -prune 可以翻译为:如果目录不可读,请不要进入该目录 .

    • -readable 测试考虑了 -perm 测试忽略的访问控制列表和其他权限假象 .

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

  • 182

    简单回答:

    find . > files_and_folders 2>&-

    2>&-关闭( - )标准错误文件描述符( 2 ),以便所有错误消息都被静音 .

    • 如果否则会打印任何' Permission denied '错误,退出代码仍为 1

    GNU查找的强大答案:

    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 standard的一部分

    • 可能仍会在异常/损坏的文件上返回' Permission denied '(例如,请参阅bug report,使用 lxcfs <v2.0.5影响装有容器的文件系统)

    适用于任何POSIX兼容查找(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 使用environment variable3>&2 2>&1 1>&33>&2 2>&1 duplicate file descriptorsPOSIX locale设置为将标准错误流传递给 grep[ $? = 1 ] 使用[]grep 返回的错误代码反转为近似 find 的原始行为 .

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

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

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

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

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

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

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

  • 85

    使用:

    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,...)的Unix版本以及任何符合POSIX标准的find版本 .

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

  • 4

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

    find . 2>/dev/null > some_file
    

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

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

相关问题