我需要隐藏所有被拒绝的消息:
find . > files_and_folders
当这样的信息出现时,我正在做实验。我需要收集所有的文件夹和文件,它没有出现。
是否可以将权限级别直接指向files_and_folders文件?
如何同时隐藏错误?
我需要隐藏所有被拒绝的消息:
find . > files_and_folders
当这样的信息出现时,我正在做实验。我需要收集所有的文件夹和文件,它没有出现。
是否可以将权限级别直接指向files_and_folders文件?
如何同时隐藏错误?
Use:
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
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.
这个主题有无穷无尽的变化,取决于你想做什么。这将在任何带有任何Bourne shell衍生物(Bash, Korn,…)的Unix变体和任何posix兼容版本的find上工作。
如果您希望适应系统上的find的特定版本,可能有可用的替代选项。特别是GNU find有许多其他版本没有的选项-请参阅当前接受的一组选项的答案。
重定向标准错误。例如,如果你在unix机器上使用bash,你可以像这样将标准错误重定向到/dev/null:
find . 2>/dev/null >files_and_folders
这些错误被打印到标准错误输出(fd 2)。要过滤它们,只需将所有错误重定向到/dev/null:
find . 2>/dev/null > some_file
或者首先连接stderr和stdout,然后grep出那些特定的错误:
find . 2>&1 | grep -v 'Permission denied' > some_file
我不得不使用:
find / -name expect 2>/dev/null
指定我想要查找的名称,然后告诉它将所有错误重定向到/dev/null
expect是我正在搜索的expect程序的位置。
如果你想从根目录“/”开始搜索,你可能会看到如下输出:
find: /./proc/1731/fdinfo: Permission denied
find: /./proc/2032/task/2032/fd: Permission denied
这是因为许可。要解决这个问题:
可以使用sudo命令: Sudo find /。- name“toBeSearched.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'
您还可以使用-perm和-prune谓词来避免下降到不可读的目录(参见如何从查找程序中删除“拒绝权限”打印输出语句?- Unix和Linux Stack Exchange):
find . -type d ! -perm -g+r,u+r,o+r -prune -o -print > files_and_folders
Use:
find . ! -readable -prune -o -print
或者更一般地说
find <paths> ! -readable -prune -o <other conditions like -name> -print
避免“拒绝许可” 并且不要压制(其他)错误消息 AND获得退出状态0(“所有文件已成功处理”)
使用:find (GNU findutils) 4.4.2。 背景:
-readable测试匹配可读文件。!当test为false时,运算符返回true。和!-readable匹配不可读目录(&文件)。 -prune操作不会下降到目录中。 ! -readable -prune可以翻译为:如果目录不可读,不要进入该目录。 可读测试会考虑-perm测试忽略的访问控制列表和其他权限构件。
更多细节请参见(1)manpage。
为了避免出现“权限被拒绝”警告,请告诉find通过从搜索中删除不可读的文件来忽略它们。将表达式作为OR添加到查找中,例如
find / \! -readable -prune -o -name '*.jbd' -ls
这主要是说(匹配一个不可读的文件并将其从列表中删除)或(匹配一个像*这样的名称。JBD和显示它[与ls])。(请记住,默认情况下表达式是AND'd,除非使用-or。)您需要在第二个表达式中使用-ls,否则find可能会添加一个默认操作来显示任何一个匹配,这也将显示所有不可读的文件。
但是如果你在你的系统中寻找真实的文件,通常没有理由去找/dev,因为那里有很多很多的文件,所以你应该添加一个表达式来排除这个目录,比如:
find / -mount \! -readable -prune -o -path /dev -prune -o -name '*.jbd' -ls
所以(匹配不可读的文件并从列表中修剪)或(匹配路径/dev并从列表中修剪)或(匹配像*。JBD并显示它)。
虽然上述方法不能解决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。
注意:
这个答案可能比用例更深入,在许多情况下,找到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.
上面的答案对我都没用。我在网上找到的东西都集中在:隐藏错误。没有正确处理进程返回码/退出码。我在bash脚本中使用命令find来定位一些目录,然后检查它们的内容。我计算命令查找成功使用退出代码:值为零工作,否则失败。
Michael 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脚本解决方案更改为:
find /home*/ -maxdepth 5 -follow \ \(type d -a !\(-readable -a -executable \) \) -删除\ - o \ \(-type d -a -readable -a -executable -name "${m_find_name}" \) -打印
这里的关键是在组合表达式中放置“not true”:
has read access AND has execute access
否则它没有完全访问权限,这意味着:修剪它。事实证明,在一个之前建议的解决方案失败的场景中,这对我来说是有效的。
我在评论部分提供了以下技术细节。如果细节过多,我很抱歉。
¿Why using command nice? I got the idea here. Initially I thought it would be nice to reduce process priority when looking an entire filesystem. I realized it makes no sense to me, as my script is limited to few directories. I reduced -maxdepth to 3. ¿Why search within /home*/? This it not relevant for this thread. I install all applications by hand via source code compile with non privileged users (not root). They are installed within "/home". I can have multiple binaries and versions living together. I need to locate all directories, inspect and backup in a master-slave fashion. I can have more than one "/home" (several disks running within a dedicated server). ¿Why using -follow? Users might create symbolic links to directories. It's usefulness depends, I need to keep record of the absolute paths found.
简单的回答是:
找到。> 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文件本身是不可写的)
您可以使用grep -v逆匹配
-v, --invert-match select non-matching lines
是这样的:
find . > files_and_folders
cat files_and_folders | grep -v "permission denied" > files_and_folders
应该有魔力
-=适用于苹果操作系统=-
使用别名创建一个新命令:只需添加~/。bash_profile线:
alias search='find / -name $file 2>/dev/null'
在新的终端窗口中,你可以调用它:
$ file=<filename or mask>; search
例如: $ file =等;搜索
如果您正在使用CSH或TCSH,这里有一个解决方案:
( find . > files_and_folders ) >& /dev/null
如果你想输出到终端:
( find . > /dev/tty ) >& /dev/null
然而,正如“CSH -whynot”常见问题所描述的那样,您不应该使用CSH。
只需使用它在系统中搜索文件。
find / name YOUR_SEARCH_TERM 2>&1 | grep YOUR_SEARCH_TERM
我们不要做不必要的工程,你只是想搜索你的文件,对吧?然后,如果文件出现在您可访问的区域,该命令将为您列出文件。
GNU find†的优化解决方案
至少对于某些系统+文件系统组合,find不需要统计文件来获取其类型。然后,您可以在测试可读性之前检查它是否是一个目录,以加快搜索‡-我在测试中获得了约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
笔记
†可读的和,(逗号)操作符是GNU扩展。这个表达式
$ find . [expression] , [expression]
逻辑上等价于
$ find . \( [expression] -o -true \) [expression]
‡这是因为启用此优化的查找实现将避免在所讨论的用例中声明非目录文件。
编辑: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中的糟糕输出…运行时间似乎是相等的。
为了在整个文件系统中搜索某些文件,例如主机,除了会导致各种错误的/proc树,我使用以下方法:
# find / -path /proc ! -prune -o -name hosts -type f
/etc/hosts
注意:因为-prune始终为真,所以必须对其求反,以避免在输出中看到行/proc。我试过了!-readable方法,并发现它返回/proc下当前用户可以读取的所有内容。所以"OR"条件并不是你所期望的。
我从find手册页给出的示例开始,参见-prune选项。