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

find . > files_and_folders

当这样的信息出现时,我正在做实验。我需要收集所有的文件夹和文件,它没有出现。

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

如何同时隐藏错误?


当前回答

简单的回答是:

找到。> files_and_folders 2>&-

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

如果将打印任何“权限拒绝”错误,退出代码仍将为1

健壮的GNU答案找到:

找到。type d \!\(-readable -executable \) -prune -print -o -print >文件和文件夹

传递额外的选项来查找-prune(防止降为),但仍然-print任何(-typed)不(\!)具有-可读和-可执行权限的目录,或(-o) -print任何其他文件。

-readable和-executable选项是GNU扩展,不是POSIX标准的一部分 可能仍然会对异常/损坏的文件返回'Permission denied'(例如,参见使用lxcfs < v2.0.5影响容器挂载文件系统的错误报告)

健壮的答案,适用于任何posix兼容的查找(GNU, OSX/BSD等)

{LC_ALL=C查找。3>&2 2>&1 1>&3 > files_and_folders | grep -v '权限被拒绝';[$ ?= 1];} 3>&2 2>&1

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

LC_ALL=C使用一个环境变量设置POSIX区域设置,3>&2 2>&1 1>&3和3>&2 2>&1重复文件描述符将标准错误流管道到grep,并且[$?= 1]使用[]来反转grep返回的错误代码,以近似find的原始行为。

也会过滤任何由于输出重定向导致的“权限拒绝”错误(例如,如果files_and_folders文件本身是不可写的)

其他回答

use

sudo find / -name file.txt

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

简单的回答是:

找到。> files_and_folders 2>&-

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

如果将打印任何“权限拒绝”错误,退出代码仍将为1

健壮的GNU答案找到:

找到。type d \!\(-readable -executable \) -prune -print -o -print >文件和文件夹

传递额外的选项来查找-prune(防止降为),但仍然-print任何(-typed)不(\!)具有-可读和-可执行权限的目录,或(-o) -print任何其他文件。

-readable和-executable选项是GNU扩展,不是POSIX标准的一部分 可能仍然会对异常/损坏的文件返回'Permission denied'(例如,参见使用lxcfs < v2.0.5影响容器挂载文件系统的错误报告)

健壮的答案,适用于任何posix兼容的查找(GNU, OSX/BSD等)

{LC_ALL=C查找。3>&2 2>&1 1>&3 > files_and_folders | grep -v '权限被拒绝';[$ ?= 1];} 3>&2 2>&1

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

LC_ALL=C使用一个环境变量设置POSIX区域设置,3>&2 2>&1 1>&3和3>&2 2>&1重复文件描述符将标准错误流管道到grep,并且[$?= 1]使用[]来反转grep返回的错误代码,以近似find的原始行为。

也会过滤任何由于输出重定向导致的“权限拒绝”错误(例如,如果files_and_folders文件本身是不可写的)

通过使用2>/dev/null管道stderr到/dev/null

找到。- name”……2 > / dev / null

注意:

这个答案可能比用例更深入,在许多情况下,找到2>/dev/null就足够了。从跨平台的角度来看,它可能仍然是有兴趣的,它讨论了一些先进的shell技术,以便找到尽可能健壮的解决方案,尽管所防范的情况可能主要是假设的。


如果你的shell是bash或zsh,有一种解决方案既健壮又相当简单,只使用posix兼容的查找特性;虽然bash本身不是POSIX的一部分,但大多数现代Unix平台都附带了它,使得这个解决方案具有广泛的可移植性:

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

注意:

If your system is configured to show localized error messages, prefix the find calls below with LC_ALL=C (LC_ALL=C find ...) to ensure that English messages are reported, so that grep -v 'Permission denied' works as intended. Invariably, however, any error messages that do get displayed will then be in English as well. >(...) is a (rarely used) output process substitution that allows redirecting output (in this case, stderr output (2>) to the stdin of the command inside >(...). In addition to bash and zsh, 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 (in ksh 93u+). grep -v 'Permission denied' filters out (-v) all lines (from the find command's stderr stream) that contain the phrase Permission denied and outputs the remaining lines to stderr (>&2). Note: There's a small chance that some of grep's output may arrive after find 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仅应用于错误消息(而不应用于文件路径和错误消息的组合,可能会导致误报),并且将权限拒绝的错误消息以外的错误消息传递给stderr。 副作用free: find的退出代码被保留:无法访问遇到的至少一个文件系统项导致退出代码1(尽管它不会告诉您是否发生了权限拒绝之外的错误)。


posix兼容的解决方案:

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

如果find的输出无论如何都要被捕获到文件中(或者完全被抑制),那么Jonathan Leffler给出的基于管道的解决方案是简单、健壮且符合posix的:

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

注意,重定向的顺序很重要:2>和1必须先出现。

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

The only downside is that the overall exit code will be the grep command's, not find's, which in this case means: if there are no errors at all or only permission-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 fundamental failure such as passing a non-existent path. However, the specific case of even only some of the input paths being inaccessible due to lack of permissions is reflected in find's exit code (in both GNU and BSD find): if a permissions-denied error occurs for any of the files processed, the exit code is set to 1.

下面的变体解决了这个问题:

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

现在,退出代码指示是否发生了除Permission denied之外的任何错误:如果是1,否则为0。 换句话说:退出码现在反映了命令的真实意图:如果根本没有错误或只发生了权限拒绝错误,则报告success(0)。 可以说,这甚至比在顶部的解决方案中传递find的退出代码更好。


gniourf_gniourf在评论中提出了一个使用复杂重定向的解决方案的泛化(仍然符合posix),即使在将文件路径打印到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的,但可以应用与上面相同的修复。


关于现有答案的说明:

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 GNU find, this won't be a problem for you. Some Permission denied errors may still surface: find ! -readable -prune reports such errors for the child items of directories for which the current user does have r permission, but lacks x (executable) permission. The reason is that because the directory itself is readable, -prune is not executed, and the attempt to descend into that directory then triggers the error messages. That said, the typical case is for the r 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 printing the paths is all you do: If you conceptualize the filtering of the permission-denied error messages a separate task that you want to be able to apply to any find command, then the opposite approach of proactively preventing permission-denied errors requires introducing "noise" into the find 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 extend the command by including a -name filter, as follows: find . ! -readable -prune -o -name '*.txt' This, however, does not work as intended, because the trailing -print action is required (an explanation can be found in this answer). Such subtleties can introduce bugs. The first solution in Jonathan Leffler's answer, find . 2>/dev/null > files_and_folders, as he himself states, blindly silences all error 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 printing filenames, for security reasons: because you're running as the root user, "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.

虽然上述方法不能解决Mac OS X的情况,因为Mac OS X不支持可读开关,这是如何避免在输出中出现“权限拒绝”错误的。这可能会帮助到某些人。

查找/ -type f -name "your_pattern" 2>/dev/null。

例如,如果您使用find命令来查找目录中某些模式的文件的大小,2>/dev/null仍然可以工作,如下所示。

找到。-type f -name "your_pattern" -exec du -ch {} + 2>/dev/null | grep total$。

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