我需要隐藏所有权限被拒绝的消息:
find . > files_and_folders
当出现这样的消息时,我正在试验。我需要收集所有不会出现的文件夹和文件。
是否可以将权限级别定向到files_and_folders
文件?
如何同时隐藏错误?
我需要隐藏所有权限被拒绝的消息:
find . > files_and_folders
当出现这样的消息时,我正在试验。我需要收集所有不会出现的文件夹和文件。
是否可以将权限级别定向到files_and_folders
文件?
如何同时隐藏错误?
采用:
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
选择性,并且可能必须根据语言环境和 O/S 更改拼写)和最终>&2
意味着幸存的错误消息(写入标准输出)再次进入标准错误。最终的重定向在终端可以被认为是可选的,但是在脚本中使用它是一个非常好的主意,这样错误消息就会出现在标准错误上。
这个主题有无穷无尽的变化,这取决于你想做什么。这将适用于具有任何 Bourne shell 衍生工具(Bash、Korn 等)的任何 Unix 变体和任何符合 POSIX 标准的find
.
如果您希望适应find
系统上的特定版本,可能会有其他选项可用。特别是GNUfind
具有其他版本中不可用的无数选项 - 请参阅当前接受的一组选项的答案。
笔记:
find 2>/dev/null
在许多情况下可能已经足够好了。对于跨平台的观点和讨论一些先进的 shell 技术以找到尽可能健壮的解决方案可能仍然很有趣,即使所防范的情况可能在很大程度上是假设性的。如果您的shell 是bash
或zsh
,那么有一个解决方案既健壮又相当简单,只使用符合 POSIX 的find
特性;虽然bash
它本身不是 POSIX 的一部分,但大多数现代 Unix 平台都附带了它,这使得该解决方案具有广泛的可移植性:
find . > files_and_folders 2> >(grep -v 'Permission denied' >&2)
笔记:
如果您的系统配置为显示本地化错误消息,请在find
下面的调用前加上LC_ALL=C
( LC_ALL=C find ...
) 以确保报告英文消息,以便grep -v 'Permission denied'
按预期工作。但是,任何确实显示的错误消息都将始终以英文显示。
>(...)
是一个(很少使用的)输出 进程替换,它允许将输出(在这种情况下,stderr output ( 2>
) 重定向到内部命令的标准输入>(...)
。
除了bash
and之外zsh
,原则上ksh
也支持它们,但试图将它们与重定向结合起来stderr,就像这里 ( ) 所做的那样,似乎被默默地忽略了 (in )。2> >(...)
ksh 93u+
grep -v 'Permission denied'
过滤掉( )包含该短语的-v
所有行(来自命令的 stderr 流),并将剩余的行输出到 stderr ( )。find
Permission denied
>&2
注意:完成后grep
某些输出可能会到达的可能性很小,因为整个命令不会等待内部命令完成。在中,您可以通过附加到命令来防止这种情况。 find
>(...)
bash
| cat
这种方法是:
健壮:grep
仅适用于错误消息(而不适用于文件路径和错误消息的组合,可能导致误报),并且除了权限被拒绝的错误消息之外的错误消息被传递到标准错误。
side-effect free :find
的退出代码被保留:无法访问遇到的至少一个文件系统项目会导致退出代码1
(尽管这不会告诉您是否发生了除了权限被拒绝的错误之外的错误(也))。
完全符合 POSIX 的解决方案要么有限制,要么需要额外的工作。
如果无论如何要在文件find
中捕获 ' 的输出(或完全抑制),那么Jonathan Leffler 的答案中基于管道的解决方案是简单、健壮且符合 POSIX 的:
find . 2>&1 >files_and_folders | grep -v 'Permission denied' >&2
请注意,重定向的顺序很重要:2>&1
must come first。
预先在文件中捕获标准输出输出允许通过管道仅2>&1
发送错误消息,然后可以明确地对其进行操作。grep
唯一的缺点是整个退出代码将是grep
命令的,而不是find
,这在这种情况下意味着:如果根本没有错误或只有权限被拒绝的错误,则退出代码将是1
(signaling failure ),否则 (许可被拒绝以外的错误)0
- 这与意图相反。
也就是说,find
的退出代码无论如何都很少使用,因为它通常传达的信息很少,超出基本故障,例如通过不存在的路径。
但是,具体情况甚至只有一些由于缺少权限而无法访问的输入路径的一部分反映在find
的退出代码中(在 GNU 和 BSD 中):如果任何find
处理的文件发生权限拒绝错误,则退出代码设置为.1
以下变体解决了以下问题:
find . 2>&1 >files_and_folders | { grep -v 'Permission denied' >&2; [ $? -eq 1 ]; }
现在,退出代码指示是否发生了除此之外的任何错误: Permission denied
如果1
是,0
否则。
换句话说:退出代码现在反映了命令的真实意图: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
如果没有这些重定向,数据(文件路径)和错误消息都将grep
通过标准输出传送到,grep
然后将无法区分错误消息和 名称恰好包含短语Permission denied
的(假设的)文件。Permission denied
然而,与第一个解决方案一样,报告的退出代码将是grep
's,而不是find
's,但可以应用与上述相同的修复。
关于Michael Brux 的回答,有几点需要注意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
尾随操作(可以在这个答案中找到解释)。这种微妙之处可能会引入错误。正如他自己所说, Jonathan Leffler 的回答中的第一个解决方案会盲目地使所有错误消息静音(而且解决方法很麻烦,而且并不完全可靠,正如他所解释的那样)。然而,务实地说,这是最简单的解决方案,因为您可能满足于假设任何和所有错误都与权限相关。find . 2>/dev/null > files_and_folders
薄雾的答案,简洁实用sudo find . > files_and_folders
,但出于安全原因,除了打印文件名之外,其他任何事情都是不明智的:因为你以root用户身份运行,“你有可能让你的整个系统被 find 中的错误搞砸或恶意版本,或意外写入某些内容的错误调用,如果您以正常权限运行此操作,则不会发生这种情况”(来自Tripleee对雾的回答的评论)。
viraptor 的答案中的第二个解决方案存在误报的find . 2>&1 | grep -v 'Permission denied' > some_file
风险(由于通过管道发送 stdout 和 stderr 的混合),并且可能不是通过 stderr报告非许可拒绝错误,而是在输出路径旁边捕获它们在输出文件中。
采用:
find . ! -readable -prune -o -print
或更一般地说
find <paths> ! -readable -prune -o <other conditions like -name> -print
适用于:find (GNU findutils) 4.4.2。背景:
-readable
匹配可读文件。当!
测试为假时,运算符返回真。并! -readable
匹配不可读的目录(&files)。-prune
操作不会下降到目录中。! -readable -prune
可以翻译为:如果目录不可读,请不要深入其中。-readable
测试考虑了访问控制列表和-perm
测试忽略的其他权限伪影。有关更多详细信息,另请参见find
(1) 联机帮助页。
如果您想从根目录 "/" 开始搜索,您可能会看到如下输出:
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
您可以使用将标准错误输出从(通常显示/屏幕)重定向到标准输出(通常显示/屏幕),然后使用带有 -v "invert" 参数的 grep 命令进行管道传输,以查看具有“权限被拒绝”的输出行词对:
find /. -name 'toBeSearched.file' 2>&1 | grep -v 'Permission denied'
我不得不使用:
find / -name expect 2>/dev/null
指定我想要查找的名称,然后告诉它将所有错误重定向到 /dev/null
期望是我正在寻找的期望程序的位置。
使用2>/dev/null进行管道stderr
传输/dev/null
find . -name '...' 2>/dev/null
您还可以使用-perm
and-prune
谓词来避免进入不可读的目录(另请参阅如何从 find 程序中删除“permission denied”打印输出语句?- Unix & Linux Stack Exchange):
find . -type d ! -perm -g+r,u+r,o+r -prune -o -print > files_and_folders
重定向标准错误。例如,如果您在 unix 机器上使用 bash,您可以将标准错误重定向到 /dev/null,如下所示:
find . 2>/dev/null >files_and_folders
虽然上述方法不能解决 Mac OS X 的情况,因为 Mac OS X 不支持-readable
switch,但这是您可以避免输出中出现“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$
.
这将返回给定模式的文件的总大小。注意2>/dev/null
find 命令末尾的。
这些错误被打印到标准错误输出 (fd 2)。要过滤掉它们,只需将所有错误重定向到 /dev/null:
find . 2>/dev/null > some_file
或者先加入 stderr 和 stdout,然后用 grep 找出那些特定的错误:
find . 2>&1 | grep -v 'Permission denied' > some_file
find . > files_and_folders 2>&-
2>&-
关闭 ( -
) 标准错误文件描述符 ( 2
),因此所有错误消息都被静音。
1
任何“ ”错误,退出代码仍然存在Permission denied
find
:find . -type d \! \( -readable -executable \) -prune -print -o -print > files_and_folders
将额外的选项传递给find
那个-prune
(防止下降到),但仍然是-print
任何目录()不具有()和权限,或()任何其他文件。-type
d
\!
-readable
-executable
-o
-print
-readable
和-executable
options 是 GNU 扩展,不是POSIX 标准的一部分Permission denied
在异常/损坏的文件上返回“”(例如,请参阅影响使用< v2.0.5的容器安装文件系统的错误报告)lxcfs
find
(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
使用管道将标准错误流传递给grep
,删除包含该'Permission denied'
字符串的所有行。
LC_ALL=C
使用环境变量设置POSIX 语言环境,并复制文件描述符以将标准错误流通过管道传输到,并用于反转返回的错误代码以近似.3>&2 2>&1 1>&3
3>&2 2>&1
grep
[ $? = 1 ]
[]
grep
find
'Permission denied'
由于输出重定向引起的任何错误(例如,如果files_and_folders
文件本身不可写)为了避免仅仅出现权限被拒绝警告,请通过从搜索中删除它们来告诉 find 忽略不可读的文件。将表达式作为 OR 添加到您的查找中,例如
find / \! -readable -prune -o -name '*.jbd' -ls
这主要是说(匹配一个不可读的文件并从列表中删除它)或(匹配一个像*.jbd这样的名称并显示它 [with ls])。(请记住,默认情况下,除非您使用 -or,否则表达式是 AND 一起使用的。)您需要在第二个表达式中使用 -ls,否则 find 可能会添加一个默认操作来显示任一匹配项,这也会显示所有不可读的文件.
但是如果你在你的系统上寻找真实的文件,通常没有理由去寻找 /dev,它有很多很多的文件,所以你应该添加一个不包括那个目录的表达式,比如:
find / -mount \! -readable -prune -o -path /dev -prune -o -name '*.jbd' -ls
所以(匹配不可读的文件并从列表中修剪)或(匹配路径 /dev 并从列表中修剪)或(匹配*.jbd之类的文件并显示它)。
采用
sudo find / -name file.txt
这很愚蠢(因为你提升了搜索)并且不安全,但写起来要短得多。
以上答案都不适合我。我在 Internet 上找到的所有内容都集中在:隐藏错误。None 正确处理进程返回代码/退出代码。我在 bash 脚本中使用命令 find 来定位一些目录,然后检查它们的内容。我使用退出代码评估命令 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 脚本解决方案更改为:
不错的发现 /home*/ -maxdepth 5 -follow \
\( -type d -a ! \( -readable -a -executable \) \) -prune \
-o \
\( -type d -a -readable -a -可执行文件 -a -name "${m_find_name}" \) -print
这里的关键是为组合表达式放置“不正确”:
has read access AND has execute access
否则它没有完全访问权限,这意味着:修剪它。事实证明,在以前建议的解决方案失败的一种情况下,这对我有用。
我在评论部分提供了以下问题的技术细节。如果细节过多,我深表歉意。
您可以使用 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
应该到魔法
-=对于 MacOS=-
使用别名创建一个新命令:只需添加 ~/.bash_profile 行:
alias search='find / -name $file 2>/dev/null'
在新的终端窗口中,您可以调用它:
$ file=<filename or mask>; search
例如:
$文件=等;搜索
如果您使用的是 CSH 或 TCSH,这里有一个解决方案:
( find . > files_and_folders ) >& /dev/null
如果要输出到终端:
( find . > /dev/tty ) >& /dev/null
只需使用它来搜索系统中的文件。
find / -name YOUR_SEARCH_TERM 2>&1 | grep YOUR_SEARCH_TERM
让我们不要做不必要的过度工程,您只想搜索您的文件对吗?如果文件存在于您可以访问的区域中,那么该命令将为您列出文件。
find
†的优化解决方案</sup>至少对于某些系统+文件系统组合,find
不需要stat
文件来获取其类型。然后,您可以在测试可读性之前检查它是否是一个目录,以加快搜索速度‡</sup> — 我所做的测试有 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
†</sup>-readable
和,
(逗号)运算符是 GNU 扩展。这个表达
$ find . [expression] , [expression]
逻辑上等价于
$ find . \( [expression] -o -true \) [expression]
‡</sup> 这是因为find
启用此优化的实现将stat
在讨论的用例中完全避免使用非目录文件。
这是我最终使用的 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 中的错误输出......运行时间似乎是相同的。
最小的解决方案就是添加readable
标志。
find . -name foo -readable