bash 如何从“查找”中排除所有“权限被拒绝”消息?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/762348/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I exclude all "permission denied" messages from "find"?
提问by Léo Léopold Hertz ??
I need to hide all permission deniedmessages from:
我需要隐藏所有权限被拒绝的消息:
find . > files_and_folders
I am experimenting when such message arises. I need to gather all folders and files, to which it does not arise.
当这样的消息出现时,我正在试验。我需要收集它不会出现的所有文件夹和文件。
Is it possible to direct the permission levels to the files_and_folders
file?
是否可以将权限级别定向到files_and_folders
文件?
How can I hide the errors at the same time?
如何同时隐藏错误?
采纳答案by mklement0
Note:
* This answer probably goes deeper than the use case warrants, and find 2>/dev/null
may be good enough in many situations. It may still be of interest for a cross-platform perspective and for its discussion of some advanced shell techniques in the interest of finding a solution that is as robust as possible, even though the cases guarded against may be largely hypothetical.
* If your system is configured to show localizederror messages, prefix the find
calls below with LC_ALL=C
(LC_ALL=C find ...
) to ensure that Englishmessages are reported, so that grep -v 'Permission denied'
works as intended. Invariably, however, any error messages that doget displayed will then be in English as well.
注意:
* 这个答案可能比用例保证的更深入,并且find 2>/dev/null
在许多情况下可能已经足够了。尽管所防范的情况可能在很大程度上是假设的,但对于跨平台的观点及其对一些高级 shell 技术的讨论,以找到尽可能健壮的解决方案,它可能仍然很有趣。
*如果您的系统配置为显示本地化的错误消息,请在find
下面的调用前加上LC_ALL=C
( LC_ALL=C find ...
) 以确保报告英文消息,以便grep -v 'Permission denied'
按预期工作。不变的是,然而,任何错误消息也得到显示届时将在学英文。
If your shell is bash
or zsh
, there's a solution that is robust while being reasonably simple, using only POSIX-compliant find
features; while bash
itself is not part of POSIX, most modern Unix platforms come with it, making this solution widely portable:
如果您的shell 是bash
或zsh
,则有一个既健壮又相当简单的解决方案,仅find
使用符合 POSIX 的功能;虽然bash
它本身不是 POSIX 的一部分,但大多数现代 Unix 平台都附带了它,使这个解决方案具有广泛的可移植性:
find . > files_and_folders 2> >(grep -v 'Permission denied' >&2)
Note: There's a small chance that some of grep
's output may arrive afterfind
completes, because the overall command doesn't wait for the command inside >(...)
to finish. In bash
, you can prevent this by appending | cat
to the command.
注:有一个小的机会,一些grep
的输出可以到达之后find
完成,因为整体命令不会等待命令内部>(...)
来完成。在 中bash
,您可以通过附加| cat
到命令来防止这种情况。
>(...)
is a (rarely used) outputprocess substitutionthat allows redirecting output (in this case, stderroutput (2>
) to the stdin of the command inside>(...)
.
In addition tobash
andzsh
,ksh
supports them as well in principle, but trying to combine them with redirection from stderr, as is done here (2> >(...)
), appears to be silently ignored (inksh 93u+
).grep -v 'Permission denied'
filters out(-v
) all lines (from thefind
command's stderr stream) that contain the phrasePermission denied
and outputs the remaining lines to stderr (>&2
).
>(...)
是一个(很少使用的)输出过程替换,它允许将输出(在这种情况下,stderr输出(2>
)重定向到内部命令的 stdin>(...)
。
除了bash
and 之外zsh
,原则上ksh
也支持它们,但尝试将它们与重定向结合起来)stderr,就像这里 ( )所做的那样,似乎被默默地忽略了 (in )。2> >(...)
ksh 93u+
grep -v 'Permission denied'
过滤掉(-v
)find
包含短语的所有行(来自命令的 stderr 流)Permission denied
并将剩余的行输出到 stderr (>&2
)。
This approach is:
这种方法是:
robust:
grep
is only applied to error messages(and not to a combination of file paths and error messages, potentially leading to false positives), and error messages other than permission-denied ones are passed through, to stderr.side-effect free:
find
's exit code is preserved: the inability to access at least one of the filesystem items encountered results in exit code1
(although that won't tell you whether errors otherthan permission-denied ones occurred (too)).
健壮:
grep
仅适用于错误消息(而不是文件路径和错误消息的组合,可能会导致误报),并且除了权限被拒绝的错误消息之外的错误消息被传递到 stderr。无副作用:
find
的退出代码被保留:无法访问遇到导致退出代码文件系统项目中的至少一个1
(虽然这不会告诉你的错误是否其他比许可被拒绝的人发生了(太))。
POSIX-compliant solutions:
符合 POSIX 的解决方案:
Fully POSIX-compliant solutions either have limitations or require additional work.
完全符合 POSIX 的解决方案要么有局限性,要么需要额外的工作。
If find
's output is to be captured in a fileanyway(or suppressed altogether), then the pipeline-based solution from Jonathan Leffler's answeris simple, robust, and POSIX-compliant:
如果无论如何find
都要在文件中捕获 的输出(或完全抑制),那么Jonathan Leffler 的答案中基于管道的解决方案是简单、健壮且符合 POSIX 标准的:
find . 2>&1 >files_and_folders | grep -v 'Permission denied' >&2
Note that the order of the redirections matters: 2>&1
must come first.
请注意,重定向的顺序很重要:2>&1
must come first。
Capturing stdout output in a file up front allows 2>&1
to send onlyerror messages through the pipeline, which grep
can then unambiguously operate on.
预先在文件中捕获 stdout 输出允许仅通过管道2>&1
发送错误消息,然后可以明确地对其进行操作。grep
The only downside is that the overall exit codewill be the grep
command's, not find
's, which in this case means: if there are noerrors at all or onlypermission-denied errors, the exit code will be 1
(signaling failure), otherwise (errors other than permission-denied ones) 0
- which is the opposite of the intent.
That said, find
's exit code is rarely used anyway, as it often conveys little information beyond fundamentalfailure such as passing a non-existent path.
However, the specific case of even only someof the input paths being inaccessible due to lack of permissions isreflected in find
's exit code (in both GNU and BSD find
): if a permissions-denied error occurs for anyof the files processed, the exit code is set to 1
.
该唯一的缺点是,整体退出代码将是grep
命令的,不是find
的,在这种情况下是指:如果有没有在所有或错误,只允许被拒绝的错误,退出代码会被1
(信号失效),否则(除权限被拒绝的错误之外的错误)0
- 这与意图相反。
也就是说,find
无论如何都很少使用,的退出代码,因为它通常传达的信息很少,除了基本故障之外,例如传递了不存在的路径。
然而,甚至只有一些的具体情况输入路径不可访问由于缺乏权限的是反映在find
的退出代码(在GNU和BSD find
):如果出现权限被拒绝的错误任何处理的文件的,退出代码被设定为1
。
The following variation addresses that:
以下变体解决了:
find . 2>&1 >files_and_folders | { grep -v 'Permission denied' >&2; [ $? -eq 1 ]; }
Now, the exit code indicates whether any errors other thanPermission denied
occurred: 1
if so, 0
otherwise.
In other words: the exit code now reflects the true intent of the command: success (0
) is reported, if no errors at all or onlypermission-denied errors occurred.
This is arguably even better than just passing find
's exit code through, as in the solution at the top.
现在,退出代码指示是否发生了除Permission denied
发生之外的任何错误:1
如果是,0
否则。
换句话说:退出代码现在反映了命令的真实意图:0
如果根本没有错误或仅发生权限拒绝错误,则报告成功 ( ) 。
这可以说比仅仅传递find
的退出代码更好,就像在顶部的解决方案中一样。
gniourf_gniourfin the comments proposes a (still POSIX-compliant) generalization of this solution using sophisticated redirections, which works even with the default behavior of printing the file paths to stdout:
gniourf_gniourf在评论中建议使用复杂的重定向(仍然符合 POSIX 标准)对此解决方案的概括,即使将文件路径打印到stdout的默认行为也能正常工作:
{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1
In short: Custom file descriptor 3
is used to temporarily swap stdout (1
) and stderr (2
), so that error messages alonecan be piped to grep
via stdout.
简而言之:自定义文件描述符3
用于临时交换 stdout ( 1
) 和 stderr ( 2
),以便可以通过 stdout将错误消息单独传输到管道grep
。
Without these redirections, both data (file paths) anderror messages would be piped to grep
via stdout, and grep
would then not be able to distinguish between error messagePermission denied
and a (hypothetical) file whose name happens to containthe phrase Permission denied
.
如果没有这些重定向,数据(文件路径)和错误消息都将grep
通过标准输出通过管道传输,grep
然后将无法区分错误消息Permission denied
和名称恰好包含短语Permission denied
.
As in the first solution, however, the the exit code reported will be grep
's, not find
's, but the same fix as above can be applied.
但是,与第一个解决方案一样,报告的退出代码将是grep
's,而不是find
's,但可以应用与上述相同的修复程序。
Notes on the existing answers:
关于现有答案的注释:
There are several points to note about Michael Brux's answer,
find . ! -readable -prune -o -print
:It requires GNU
find
; notably, it won't work on macOS. Of course, if you only ever need the command to work with GNUfind
, this won't be a problem for you.Some
Permission denied
errors may stillsurface:find ! -readable -prune
reports such errors for the childitems of directories for which the current user does haver
permission, but lacksx
(executable) permission. The reason is that because the directory itself isreadable,-prune
is not executed, and the attempt to descend intothat directory then triggers the error messages. That said, the typicalcase is for ther
permission to be missing.Note: The following point is a matter of philosophy and/or specific use case, and you may decide it is not relevant to you and that the command fits your needs well, especially if simply printingthe paths is all you do:
- Ifyou conceptualize the filtering of the permission-denied error messages a separatetask that you want to be able to apply to any
find
command, then the opposite approach of proactively preventingpermission-denied errors requires introducing "noise" into thefind
command, which also introduces complexity and logical pitfalls. - For instance, the most up-voted comment on Michael's answer (as of this writing) attempts to show how to extendthe command by including a
-name
filter, as follows:find . ! -readable -prune -o -name '*.txt'
This, however, does notwork as intended, because the trailing-print
action is required(an explanation can be found in this answer). Such subtleties can introduce bugs.
- Ifyou conceptualize the filtering of the permission-denied error messages a separatetask that you want to be able to apply to any
The first solution in Jonathan Leffler's answer,
find . 2>/dev/null > files_and_folders
, as he himself states, blindly silences allerror messages(and the workaround is cumbersome and not fully robust, as he also explains). Pragmatically speaking, however, it is the simplest solution, as you may be content to assume that any and all errors would be permission-related.mist's answer,
sudo find . > files_and_folders
, is concise and pragmatic, but ill-advised for anything other than merely printingfilenames, for security reasons: because you're running as the rootuser, "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" (from a comment on mist's answer by tripleee).The 2nd solution in viraptor's answer,
find . 2>&1 | grep -v 'Permission denied' > some_file
runs the risk of false positives (due to sending a mix of stdout and stderr through the pipeline), and, potentially, instead of reporting non-permission-denied errors via stderr, captures them alongside the output paths in the output file.
关于Michael Brux 的回答,有几点需要注意
find . ! -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
操作(可以在这个答案中找到解释)。这种微妙之处可能会引入错误。
- 如果您将权限拒绝错误消息的过滤概念化为一个单独的任务,您希望能够将其应用于任何
在第一个解决方案乔纳森·莱弗勒的回答,
find . 2>/dev/null > files_and_folders
如他自己陈述, 一味沉默所有的错误信息(和解决方法很麻烦并没有完全健壮,他也解释了)。然而,从实用的角度来说,这是最简单的解决方案,因为您可能满足于假设任何和所有错误都与权限相关。mis 的回答,
sudo find . > files_and_folders
,简洁而实用,但出于安全原因,除了打印文件名之外,其他任何事情都不明智:因为您以root用户身份运行,“您可能会面临整个系统被 find 中的错误搞砸的风险或恶意版本,或意外写入某些内容的错误调用,如果您以正常权限运行它,则不会发生这种情况”(来自三重雾对雾的回答的评论)。在第二个解决方案viraptor的答案,
find . 2>&1 | grep -v 'Permission denied' > some_file
运行误报的风险(由于通过管道传送输出和错误的混合),以及潜在的,而不是报告非旁边的输出路径通过stderr -permission被拒绝的错误,捕捉他们在输出文件中。
回答by Jonathan Leffler
Use:
用:
find . 2>/dev/null > files_and_folders
This hides not just the Permission denied
errors, of course, but all error messages.
Permission denied
当然,这不仅隐藏了错误,还隐藏了所有错误消息。
If you really want to keep other possible errors, such as too many hops on a symlink, but not the permission denied ones, then you'd probably have to take a flying guess that you don't have many files called 'permission denied' and try:
如果您真的想保留其他可能的错误,例如符号链接上的跳数过多,而不是权限被拒绝的错误,那么您可能不得不猜测您没有很多名为“权限被拒绝”的文件并尝试:
find . 2>&1 | grep -v 'Permission denied' > files_and_folders
If you strictly want to filter just standard error, you can use the more elaborate construction:
如果您只想过滤标准错误,则可以使用更复杂的构造:
find . 2>&1 > files_and_folders | grep -v 'Permission denied' >&2
The I/O redirection on the find
command is: 2>&1 > files_and_folders |
.
The pipe redirects standard output to the grep
command and is applied first. The 2>&1
sends standard error to the same place as standard output (the pipe). The > files_and_folders
sends standard output (but not standard error) to a file. The net result is that messages written to standard error are sent down the pipe and the regular output of find
is written to the file. The grep
filters the standard output (you can decide how selective you want it to be, and may have to change the spelling depending on locale and O/S) and the final >&2
means that the surviving error messages (written to standard output) go to standard error once more. The final redirection could be regarded as optional at the terminal, but would be a very good idea to use it in a script so that error messages appear on standard error.
find
命令上的 I/O 重定向是:2>&1 > files_and_folders |
。管道将标准输出重定向到grep
命令并首先应用。的2>&1
发送标准误差相同的地方标准输出(管)。的> files_and_folders
发送标准输出(但不是标准误差)到一个文件。最终结果是写入标准错误的消息通过管道发送,并且常规输出find
写入文件。在grep
标准输出(你可以决定如何选择性,你希望它是,并且可能不得不改变取决于语言环境和O / S的拼写)和最终过滤器>&2
意味着幸存的错误消息(写入标准输出)再次进入标准错误。最终的重定向在终端可以被视为可选的,但是在脚本中使用它是一个很好的主意,这样错误消息就会出现在标准错误上。
There are endless variations on this theme, depending on what you want to do. This will work on any variant of Unix with any Bourne shell derivative (Bash, Korn, …) and any POSIX-compliant version of find
.
这个主题有无穷无尽的变化,这取决于你想要做什么。这将适用于具有任何 Bourne shell 衍生产品(Bash、Korn 等)的任何 Unix 变体和任何 POSIX 兼容版本的find
.
If you wish to adapt to the specific version of find
you have on your system, there may be alternative options available. GNU find
in particular has a myriad options not available in other versions — see the currently accepted answer for one such set of options.
如果您希望适应系统上的特定版本find
,则可能有其他选项可用。find
特别是GNU有无数其他版本中没有的选项——请参阅当前接受的一组这样的选项的答案。
回答by Michael Brux
Use:
用:
find . ! -readable -prune -o -print
or more generally
或更一般地
find <paths> ! -readable -prune -o <other conditions like -name> -print
- to avoid "Permission denied"
- AND do NOT suppress (other) error messages
- AND get exit status 0 ("all files are processed successfully")
- 避免“权限被拒绝”
- 并且不要抑制(其他)错误消息
- 并获得退出状态 0(“所有文件均已成功处理”)
Works with: find (GNU findutils) 4.4.2. Background:
适用于:find (GNU findutils) 4.4.2。背景:
- The
-readable
test matches readable files. The!
operator returns true, when test is false. And! -readable
matches not readable directories (&files). - The
-prune
action does not descend into directory. ! -readable -prune
can be translated to: if directory is not readable, do not descend into it.- The
-readable
test takes into account access control lists and other permissions artefacts which the-perm
test ignores.
- 该
-readable
测试匹配可读文件。!
当 test 为假时,运算符返回真。并! -readable
匹配不可读的目录(&files)。 - 该
-prune
操作不会下降到目录中。 ! -readable -prune
可以翻译为:如果目录不可读,不要下降到它。- 该
-readable
测试考虑了-perm
测试忽略的访问控制列表和其他权限人工制品。
See also find
(1) manpagefor many more details.
有关更多详细信息,另请参阅find
(1) 联机帮助页。
回答by Fatih Aksu
If you want to start search from root "/" , you will probably see output somethings like:
如果您想从根目录 "/" 开始搜索,您可能会看到如下输出:
find: /./proc/1731/fdinfo: Permission denied
find: /./proc/2032/task/2032/fd: Permission denied
It's because of permission. To solve this:
是因为权限。要解决这个问题:
You can use sudo command:
sudo find /. -name 'toBeSearched.file'
您可以使用 sudo 命令:
sudo find /. -name 'toBeSearched.file'
It asks super user's password, when enter the password you will see result what you really want. If you don't have permission to use sudo command which means you don't have super user's password, first ask system admin to add you to the sudoers file.
它询问超级用户的密码,当输入密码时,您将看到您真正想要的结果。如果您无权使用 sudo 命令,这意味着您没有超级用户的密码,请首先要求系统管理员将您添加到 sudoers 文件中。
You can use redirect the Standard Error Output from (Generally Display/Screen) to some file and avoid seeing the error messages on the screen! redirect to a special file /dev/null :
find /. -name 'toBeSearched.file' 2>/dev/null
You can use redirect the Standard Error Output from (Generally Display/Screen) to Standard output (Generally Display/Screen), then pipe with grep command with -v "invert" parameter to not to see the output lines which has 'Permission denied' word pairs:
find /. -name 'toBeSearched.file' 2>&1 | grep -v 'Permission denied'
您可以使用将标准错误输出从(通常为显示/屏幕)重定向到某个文件,避免在屏幕上看到错误消息!重定向到一个特殊文件 /dev/null :
find /. -name 'toBeSearched.file' 2>/dev/null
您可以使用将标准错误输出从(通常为显示/屏幕)重定向到标准输出(通常为显示/屏幕),然后使用带有 -v“invert”参数的 grep 命令进行管道传输,以不查看具有“权限被拒绝”的输出行词对:
find /. -name 'toBeSearched.file' 2>&1 | grep -v 'Permission denied'
回答by Jeremy
I had to use:
我不得不使用:
find / -name expect 2>/dev/null
specifying the name of what I wanted to find and then telling it to redirect all errors to /dev/null
指定我想要查找的内容的名称,然后告诉它将所有错误重定向到 /dev/null
expect being the location of the expect program I was searching for.
期望是我正在搜索的期望程序的位置。
回答by Matt
Pipe stderr
to /dev/null
by using 2>/dev/null
管stderr
以/dev/null
通过使用2>的/ dev / null的
find . -name '...' 2>/dev/null
find . -name '...' 2>/dev/null
回答by sdaau
You can also use the -perm
and -prune
predicates to avoid descending into unreadable directories (see also How do I remove "permission denied" printout statements from the find program? - Unix & Linux Stack Exchange):
您还可以使用-perm
和-prune
谓词来避免进入不可读的目录(另请参阅如何从查找程序中删除“权限被拒绝”打印输出语句? - Unix & Linux Stack Exchange):
find . -type d ! -perm -g+r,u+r,o+r -prune -o -print > files_and_folders
回答by Jason Coco
Redirect standard error. For instance, if you're using bash on a unix machine, you can redirect standard error to /dev/null like this:
重定向标准错误。例如,如果您在 unix 机器上使用 bash,您可以像这样将标准错误重定向到 /dev/null:
find . 2>/dev/null >files_and_folders
回答by Bunti
While above approaches do not address the case for Mac OS X because Mac Os X does not support -readable
switch this is how you can avoid 'Permission denied' errors in your output. This might help someone.
虽然上述方法不能解决 Mac OS X 的情况,因为 Mac Os X 不支持-readable
切换,这是您可以避免输出中出现“权限被拒绝”错误的方法。这可能会帮助某人。
find / -type f -name "your_pattern" 2>/dev/null
.
find / -type f -name "your_pattern" 2>/dev/null
.
If you're using some other command with find
, for example, to find the size of files of certain pattern in a directory 2>/dev/null
would still work as shown below.
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$
.
This will return the total size of the files of a given pattern. Note the 2>/dev/null
at the end of find command.
这将返回给定模式的文件的总大小。请注意2>/dev/null
find 命令末尾的 。
回答by viraptor
Those errors are printed out to the standard error output (fd 2). To filter them out, simply redirect all errors to /dev/null:
这些错误会打印到标准错误输出 (fd 2) 中。要过滤掉它们,只需将所有错误重定向到 /dev/null:
find . 2>/dev/null > some_file
or first join stderr and stdout and then grep out those specific errors:
或者首先加入 stderr 和 stdout,然后 grep 出那些特定的错误:
find . 2>&1 | grep -v 'Permission denied' > some_file