我需要隐藏所有来自以下信息的权限被拒绝消息:
find . > files_and_folders
我在尝试时遇到这样的消息。我需要收集所有未出现此类消息的文件夹和文件。
是否可以将权限级别指定到 files_and_folders
文件中?
如何同时隐藏错误?
我需要隐藏所有来自以下信息的权限被拒绝消息:
find . > files_and_folders
我在尝试时遇到这样的消息。我需要收集所有未出现此类消息的文件夹和文件。
是否可以将权限级别指定到 files_and_folders
文件中?
如何同时隐藏错误?
使用:
find . 2>/dev/null > files_and_folders
当然,这将隐藏不仅是Permission denied
错误,而是所有错误消息。
如果你真的想保留其他可能出现的错误(例如符号链接上的太多跳转),但不想保留权限被拒绝的错误,那么你可能需要猜测一下你没有许多名为“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
表示幸存的错误消息(写入标准输出)再次发送到标准错误。 最后的重定向符号在终端上可以视为可选项,但在脚本中使用它是一个非常好的主意,因此错误消息显示在标准错误上。
这个主题有无数种变化,具体取决于你想要做什么。这将适用于任何 Unix 变体,带有任何 Bourne shell 派生(Bash、Korn 等)和任何 POSIX 兼容版本的 find
。
如果你想要适应你系统上的特定版本的 find
,可能会有其他可用选项。GNU 的 find
特别有许多其他版本不具备的选项 - 可以参考当前被接受的答案中的一组选项。2>/dev/null
中没有空格! - Nik2>
是一个没有空格的单元,你可以在它和文件名之间加上空格。类似地,在其他重定向中也是如此,比如 2>&1
(将标准错误重定向到与标准输出相同的位置),或者 2>&-
关闭标准错误等等。有关其余详细信息,请参见重定向。 (上面的代码是通用的类POSIX shell,不特定于bash
。) - Jonathan Leffler/dev/null
;而第二个命令则没有。答案还提到了假设你没有任何名为“permission denied”的文件。因此,我不清楚你真正反对的是什么。 - Jonathan Leffler注意:
find 2>/dev/null
可能已经足够好了。尽管被保护的情况可能主要是假设性的,但它仍可能对于跨平台视角和讨论一些高级shell技术以寻找尽可能健壮的解决方案是有兴趣的。find . > files_and_folders 2> >(grep -v 'Permission denied' >&2)
如果您的系统配置为显示本地化的错误消息,请在下面的find
调用前加上LC_ALL=C
(LC_ALL=C find ...
),以确保报告英语消息,这样grep -v 'Permission denied'
才能按预期工作。然而,无论如何,任何显示的错误消息都将是英文。
>(...)
是一个(很少使用的)输出进程替换,允许将输出重定向(在这种情况下,将stderr输出 (2>
) 重定向到 >(...)
内部命令的stdin中。
除了bash
和zsh
之外,ksh
也基本支持它们,但尝试将它们与来自stderr的重定向组合起来,就像这里做的一样(2> >(...)
),似乎会被默默地忽略(在ksh 93u+
中)。
grep -v 'Permission denied'
过滤掉(-v
)所有包含短语Permission denied
的行(来自find
命令的stderr流),并将剩余的行输出到stderr (>&2
)。
注意:有一小部分可能会在find
完成后到达grep
的输出,因为整个命令不等待>(...)
内部命令完成。在bash
中,您可以通过将| cat
附加到命令来防止这种情况发生。
鲁棒性:仅将错误消息(而不是文件路径和错误消息的组合,可能导致误报)应用于grep
,并将权限被拒绝以外的其他错误消息传递到 stderr。
无副作用:保留了find
的退出代码: 无法访问至少一个遇到的文件系统项目会导致退出代码为1
(尽管这不会告诉您是否发生了除权限被拒绝的其他错误)。
完全符合POSIX标准的解决方案要么有限制,要么需要额外工作。
如果find
的输出无论如何都要被捕获到一个文件中(或者完全被抑制),那么基于管道的Jonathan Leffler's answer解决方案简单、健壮且符合POSIX标准:
find . 2>&1 >files_and_folders | grep -v 'Permission denied' >&2
2>&1
必须放在最前面。2>&1
仅通过管道发送错误消息,这样grep
就可以明确地操作。grep
命令的代码,而不是find
的代码。在这种情况下,如果根本没有错误或只有权限被拒绝的错误,则退出代码将为1
(表示失败),否则(除了权限被拒绝的错误之外的其他错误)为0
- 这与意图相反。find
的退出代码很少使用,因为它通常传达的信息很少,仅限于基本故障,例如传递不存在的路径。find
的退出代码中反映出来(在GNU和BSD find
中都是如此):如果处理的任何文件出现权限被拒绝的错误,则退出代码将设置为1
。以下变化解决了这个问题:
find . 2>&1 >files_and_folders | { grep -v 'Permission denied' >&2; [ $? -eq 1 ]; }
1
表示有错误,0
表示没有错误。0
)报告。find
的退出代码更好。
gniourf_gniourf在评论中提出了一个仍然符合POSIX的通用解决方案,使用复杂的重定向,即使打印文件路径到stdout的默认行为也可以使用:
{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1
关于 Michael Brux's answer, 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
操作(详见 this answer 中的解释)。这样的微妙之处可能会引入错误。Jonathan Leffler's answer 中的第一个解决方案 find . 2>/dev/null > files_and_folders
,正如他自己所说,盲目地消除了所有的错误消息(而且解决方法很笨重,也不完全健壮,正如他所解释的那样)。从实用角度而言,这是最简单的解决方案,因为你可以假定任何错误都与权限有关。
mist's answer,sudo find . > files_and_folders
,简洁而实用,但除了仅仅打印文件名之外,不建议使用该命令,出于安全原因:因为你正在以root用户的身份运行,所以“你面临一个风险,即由于find中的漏洞或恶意版本、不正确的调用或写入意外内容而使整个系统被破坏,如果以正常特权运行,则不可能发生这种情况”(来自 tripleee 在 mist's answer 的评论中)。
viraptor's answer 中的第二个解决方案 find . 2>&1 | grep -v 'Permission denied' > some_file
存在误报的风险(因为将混合的 stdout 和 stderr 通过管道发送),并且可能会将非权限拒绝错误通过 stderr 报告,同时将它们与输出路径一起捕获到输出文件中。
find . 2>&1 > files_and_folders | grep -v 'Permission denied' >&2
? - gniourf_gniourf{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1
。这个命令会在当前目录下查找文件,并过滤掉权限被拒绝的文件,最后将结果输出到标准输出(屏幕)。 - gniourf_gniourf>(...)
是特定于Bash的。 - gniourf_gniourf执行/搜索
文件模式权限才能够“搜索”目录(检索所包含文件的inode)。为了进入子目录(除需要读取
权限以列出目录中的文件外),find
命令也需要这样做。这不是一个“错误”或“移植错误”。 - wjordan使用:
find . ! -readable -prune -o -print
或更加普遍地说
find <paths> ! -readable -prune -o <other conditions like -name> -print
适用于:find(GNU findutils)4.4.2。
-readable
测试匹配可读取的文件。当测试结果为false时,!
操作符返回true。而! -readable
则匹配不可读取的目录和文件。-prune
操作不会进入目录。! -readable -prune
可以翻译为:如果目录不可读,则不进入它。-readable
测试考虑到访问控制列表和其他权限因素,而-perm
测试则忽略它们。有关更多详细信息,请参见find
(1)手册页。
-o
:find . ! -readable -prune -o -name '*.txt'
。 - tempestadeptfind
命令不包括-readable
选项;同样,BSD的find
命令以及Mac OS X的find
命令也不包括该选项(我不确定其他系统是否有此选项)。因此,如果您无法保证系统安装了GNU find
命令,则不太明显如何进行调整。在拥有GNU find
可用的Linux系统中,该命令非常有效,而在其他系统上则可能会有所不同。 - Jonathan Lefflerfind . ! -readable -prune -o -name '*.txt'
在使用 find 4.2.2 进行 Ubuntu 14.04 上似乎无法正常工作。它似乎忽略了 -name
。出于某些奇怪的原因,find . \( ! -readable -prune \) -o -name '*.txt' -print
可以成功运行。 - con-f-use如果您希望从根目录"/"开始搜索,您可能会看到类似以下的输出:
find: /./proc/1731/fdinfo: Permission denied
find: /./proc/2032/task/2032/fd: Permission denied
这是因为权限问题。要解决这个问题:
你可以使用sudo命令:
sudo find /. -name 'toBeSearched.file'
该命令会要求输入超级用户密码,当你输入密码后你将看到想要的结果。如果你没有使用sudo命令的权限,这意味着你没有超级用户的密码,首先向系统管理员请求将你添加到sudoers文件中。
你可以使用重定向标准错误输出来避免在屏幕上看到错误信息!将其重定向到特殊文件/dev/null:
find /. -name 'toBeSearched.file' 2>/dev/null
你可以将标准错误输出重定向到标准输出(通常为显示/屏幕),然后使用grep命令并带有-v“invert”参数进行管道操作,以不显示具有“Permission denied”单词对的输出行。find /. -name 'toBeSearched.file' 2>&1 | grep -v 'Permission denied'
我不得不使用:
find / -name expect 2>/dev/null
我指定了要查找的名称,然后告诉它将所有错误重定向到/dev/null。
期望是我正在搜索的expect程序的位置。
expect
。相反,expect
只是此命令将尝试查找的文件的名称。 - Dhruv Kapoor使用2>/dev/null将stderr
导向到/dev/null
。
find . -name '...' 2>/dev/null
find . -name '...' -print 2>/dev/null
。 - shadowsheep您还可以使用 -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
-perm -g+r,u+r,o+r
仅匹配对于文件的所有3个安全主体设置了r
(读取)权限的文件,这与当前用户是否能够读取该文件没有直接关系。它有可能会错过当前用户可以读取的文件,并匹配他们无法读取的文件。 - mklement0find . -type d ! \( -perm -u+r -o -perm -g+r -o -perm -o+r \) -prune -o -print
是一个好的解决方案。 - Mattia72echo 'hi' > file; sudo chown nobody:nobody file; sudo chmod o-r file; find file -perm -u=r
会打印出file
,因为它的用户读取位被设置了,但它与当前用户无关。当前用户无法读取此文件;尝试cat file
。另请参见:我的这个答案。 - mklement0重定向标准错误。例如,在Unix机器上使用bash时,您可以将标准错误重定向到/dev/null,如下所示:
find . 2>/dev/null >files_and_folders
尽管上述方法不能解决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
。
2>/dev/null
这一部分。你可以解释一下-exec du -ch {} + 2>/dev/null | grep total$
这一部分吗? - Léo Léopold Hertz 준영-exec
选项与任何命令一起使用,以对find
命令找到的文件或目录采取进一步的操作。 du -ch file_pattern
计算匹配file_pattern
的每个文件的大小,并且该输出的最后一行是匹配file_pattern
的所有文件的总和。请参阅du
的man页面。 grep total
只过滤提取总和的行(即最后一行)。 - Bunti这些错误信息被打印到标准错误输出流(fd 2)中。要过滤掉它们,只需将所有错误重定向到/dev/null:
find . 2>/dev/null > some_file
或者先将stderr和stdout合并,然后再使用grep过滤出那些特定的错误信息:
find . 2>&1 | grep -v 'Permission denied' > some_file
find /. -name 'toBeSearched.file' 2>/dev/null
。 - HoldOffHunger