我需要隐藏以下所有拒绝权限的消息:
find . > files_and_folders
我正在尝试何时出现此类消息。我需要收集所有不会出现的文件夹和文件。
是否可以将权限级别定向到files_and_folders
文件?
如何同时隐藏错误?
我需要隐藏以下所有拒绝权限的消息:
find . > files_and_folders
我正在尝试何时出现此类消息。我需要收集所有不会出现的文件夹和文件。
是否可以将权限级别定向到files_and_folders
文件?
如何同时隐藏错误?
Answers:
注意:
*这个答案可能比用例需要的要深,并且find 2>/dev/null
在许多情况下可能已经足够了。对于跨平台的观点及其对某些高级Shell技术的讨论,尽管寻找的方案可能是假设性的,但仍可能会引起人们的兴趣,以便找到一种尽可能健壮的解决方案。
* 如果您的系统配置为显示本地化的错误消息,请在find
下面的调用前面加上LC_ALL=C
(LC_ALL=C find ...
),以确保报告了英语消息,从而可以grep -v 'Permission denied'
正常工作。但是,无论如何,任何确实显示的错误消息都将同时以英语显示。
如果您的外壳是bash
orzsh
,则有一个解决方案既健壮又相当简单,仅find
使用POSIX兼容功能;尽管bash
它本身不是POSIX的一部分,但大多数现代Unix平台都附带了它,从而使该解决方案可广泛移植:
find . > files_and_folders 2> >(grep -v 'Permission denied' >&2)
注意:完成的某些grep
输出很有可能会在 find
完成后到达,因为整体命令不会等待内部命令>(...)
完成。在中bash
,您可以通过附加| cat
到命令来防止这种情况。
>(...)
是(很少使用的)输出 过程替换,允许将输出(在这种情况下,将stderr output(2>
)重定向到内部命令的stdin >(...)
。
除了bash
和zsh
,原则上ksh
也支持它们,但尝试将它们与从stderr(如此处()所示)似乎被静默忽略(在中)。2> >(...)
ksh 93u+
grep -v 'Permission denied'
过滤掉(-v
)find
包含短语的所有行(从命令的stderr流中),Permission denied
并将剩余的行输出到stderr(>&2
)。这种方法是:
健壮的:grep
仅适用于错误消息(不适用于文件路径和错误消息的组合,有可能导致误报),并且除权限被拒绝的错误消息之外的其他错误消息也将传递到stderr。
free-find
of -effect::保留退出代码:无法访问遇到的至少一个文件系统项会导致退出代码1
(尽管它不会告诉您除许可被拒绝之外的其他错误是否也发生了)。
完全符合POSIX的解决方案有局限性或需要其他工作。
如果find
的输出是在被捕获文件反正(或完全抑制),然后从基于管线的解决方案乔纳森·莱弗勒的回答很简单,健壮,符合POSIX标准:
find . 2>&1 >files_and_folders | grep -v 'Permission denied' >&2
请注意,重定向的顺序很重要:2>&1
必须优先。
将stdout输出预先捕获在文件中,仅允许通过管道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 ]; }
现在,退出代码指示是否发生了除 错误以外的任何其他错误Permission denied
:1
如果是,0
否则。
换句话说:退出代码现在反映了该命令的真实意图:0
如果完全没有错误或仅发生了权限被拒绝的错误,则报告成功()。
可以说,这比仅通过find
顶部的解决方案传递退出代码更好。
gniourf_gniourf在评论中提出了(还是POSIX兼容的)这种解决方案采用先进的重定向的泛化,这与打印文件路径的默认行为作品甚至标准输出:
{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1
简而言之:自定义文件描述符3
用于临时交换stdout(1
)和stderr(2
),因此仅错误消息就可以grep
通过stdout 传递给管道。
如果没有这些重定向,数据(文件路径)和错误消息都将grep
通过stdout 传递到管道,grep
然后将无法区分错误消息 Permission denied
和名称恰好包含短语的(假设)文件Permission denied
。
但是,与第一种解决方案一样,报告的退出代码将是grep
,而不是find
,但是可以应用与上述相同的解决方案。
关于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
操作(可以在此答案中找到解释)。这样的微妙之处可能会引入错误。在第一个解决方案乔纳森·莱弗勒的回答,find . 2>/dev/null > files_and_folders
如他自己陈述, 一味沉默所有的错误信息(和解决方法很麻烦并没有完全健壮,他也解释了)。实用地说,这是最简单的解决方案,因为您可能会满意地假设所有错误都与权限相关。
雾的回答,sudo find . > files_and_folders
,简洁,务实的,但不明智的不仅仅是任何其他打印的文件名,出于安全方面的原因:是因为你作为运行根用户,“你可能有你的整个系统在发现bug被搞砸了或恶意版本,或不正确的调用会意外写入某些内容,如果您以正常特权运行此文件,则不会发生”(摘自Tripleee关于Mist的回答的评论)。
在第二个解决方案viraptor的答案,find . 2>&1 | grep -v 'Permission denied' > some_file
运行误报的风险(由于通过管道传送输出和错误的混合),以及潜在的,而不是报告非旁边的输出路径通过stderr -permission被拒绝的错误,捕捉他们在输出文件中。
{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1
>(...)
是特定于Bash的。
find
应该强调并宣传出口代码的保留:find
众所周知,出口代码是没有用的。在这里,它很可能会变成非零值(并且毫无用处)。
execute/search
文件模式权限才能“搜索”目录(检索包含的文件的inode)。find
这样做是为了进入一个子目录(除了需要read
获得列出目录中文件的权限之外)。这不是“错误”或“移植错误”。
采用:
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等)和POSIX兼容版本的Unix的任何变体上运行find
。
如果您希望适应系统上的特定版本find
,则可能有其他选择。find
特别是GNU ,有许多其他版本中没有的选项-请参阅当前接受的答案中的一组这样的选项。
2>/dev/null
,没有空间!
2>
是,没有任何空间的单个单元; 您可以在文件名和文件名之间留一个空格。与其他重定向类似,例如2>&1
(将标准错误重定向到与标准输出相同的位置),或2>&-
将标准错误关闭,等等。有关其余的详细信息,请参阅重定向。(上面的代码是类似POSIX的通用外壳,不特定于bash
。)
采用:
find . ! -readable -prune -o -print
或更一般地
find <paths> ! -readable -prune -o <other conditions like -name> -print
适用于:find(GNU findutils)4.4.2。背景:
-readable
测试匹配可读文件。!
当test为false时,运算符返回true。并! -readable
匹配不可读的目录(&files)。-prune
操作不会下降到目录中。! -readable -prune
可以翻译为:如果目录不可读,请不要进入该目录。-readable
测试考虑了访问控制列表和该-perm
测试忽略的其他权限伪像。有关更多详细信息,另请参见find
(1)联机帮助页。
-o
:find . ! -readable -prune -o -name '*.txt'
find
不包括在内-readable
。无论是否find
为BSD,因此Mac OS X的(我不知道其他系统)。因此,在您find
保证有GNU的情况下,这很好用,但是如果您不能保证系统已find
安装GNU,则如何调整它并不明显。(它在Linux上可以正常工作;它在其他地方可能也可以不工作。)
find . ! -readable -prune -o -name '*.txt'
使用find 4.2.2在Ubuntu 14.04上似乎不起作用。它似乎使人感到厌恶-name
。出于某些奇怪的原因,我成功了find . \( ! -readable -prune \) -o -name '*.txt' -print
如果要从根“ /”开始搜索,则可能会看到类似以下的输出:
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'
sudo find...
我不得不使用:
find / -name expect 2>/dev/null
指定我要查找的名称,然后告诉它将所有错误重定向到/ dev / null
期望是我正在搜索的期望程序的位置。
expect
。而是expect
仅是此命令将尝试查找的文件的名称。
使用2> / dev / null进行管道stderr
传输/dev/null
find . -name '...' 2>/dev/null
find . -name '...' -print 2>/dev/null
您还可以使用-perm
和-prune
谓词来避免进入不可读的目录(另请参见如何从查找程序中删除“ permission否认”的打印输出语句?-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
仅匹配为文件的r
所有三个安全主体设置(读取)权限的文件,这与当前用户是否可以读取该文件没有直接关系。它可能会丢失当前用户可以读取的文件,也可能会匹配他们无法读取的文件。
find . -type d ! \( -perm -u+r -o -perm -g+r -o -perm -o+r \) -prune -o -print
这将是一个很好的解决方案。
尽管上述方法不能解决Mac OS X的问题,因为Mac Os X不支持-readable
切换,所以这可以避免输出中出现“权限被拒绝”错误。这可能会帮助某人。
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命令末尾的。
2>/dev/null
。你能解释一下这个部分吗-exec du -ch {} + 2>/dev/null | grep total$
?
-exec
选项一起使用,以对通过find
命令找到的文件或目录采取进一步的措施。du -ch file_pattern
计算每个匹配的文件的大小file_pattern
,输出的最后一行是与匹配的所有文件的总数file_pattern
。请参见手册页du
。grep total
只过滤提取总计的行(这是最后一行)。
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
选项是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
文件本身不可写)echo 'hi' > file; sudo chown nobody:nobody file; sudo chmod o-r file; find file -perm -u=r
prints file
,因为它的用户读取位已设置,但与nobody
用户有关,而不是当前用户。当前用户无法读取此文件;尝试一下cat file
。
-perm
对于确定用户的当前权限似乎无效。从此答案中删除了该替代方法。
为了避免仅获得权限拒绝警告,请通过从搜索中删除不可读文件,告诉find忽略不可读文件。将表达式添加为OR,例如
find / \! -readable -prune -o -name '*.jbd' -ls
这主要是说(匹配一个不可读的文件并从列表中删除它)或(匹配一个 * .jbd之类的名称,并显示它(带有ls))。(请记住,默认情况下,除非使用-or,否则表达式将与在一起。)您需要在第二个表达式中使用-ls,否则find可能会添加一个默认操作来显示任一匹配项,这还将显示所有不可读的文件。
但是,如果要在系统上查找真实文件,通常没有理由在/ dev中查找文件,因为它有很多文件,因此应添加一个排除该目录的表达式,例如:
find / -mount \! -readable -prune -o -path /dev -prune -o -name '*.jbd' -ls
因此(匹配列表中的不可读文件和修剪)或(匹配列表中的路径/ dev和修剪)或(匹配 * .jbd之类的文件并显示)。
采用
sudo find / -name file.txt
它很愚蠢(因为您提高了搜索范围)并且不安全,但是编写起来却短得多。
sudo
。您可能会面临整个系统被错误find
或恶意版本,或者意外写入内容的错误调用弄乱的情况,如果使用普通权限运行此文件,则不会发生。
上面的答案对我都不起作用。我在Internet上找到的一切都集中在:隐藏错误。没有正确处理流程的返回码/退出码。我在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脚本解决方案更改为:
-尼斯找到/家* / -maxdepth 5 -follow \
\(型d -a \(可读-a -executable \)! \)-prune \
-o \
\(型d -a可读-a -可执行文件-a -name“ $ {m_find_name}” \)-print
此处的关键是为组合表达式放置“ not true”:
has read access AND has execute access
否则,它没有完全访问权限,这意味着:修剪它。在以前建议的解决方案失败的一种情况下,这证明对我有用。
我在“评论”部分中提供了以下技术详细信息,以解决问题。如果细节过多,我深表歉意。
nice
和find $HOME -maxdepth 5 -follow ...
?
${m_find_name}
),并包含对问题不相关的几个选项(nice
,/home*
,-maxdepth 5
,-follow
)。我添加了一个答案,可以更简洁地解决“过滤可读但非可执行目录”的特定问题,同时又保持通用性。
-=对于MacOS =-
使用别名创建新命令:只需添加〜/ .bash_profile行:
alias search='find / -name $file 2>/dev/null'
在新的“终端”窗口中,您可以调用它:
$ file=<filename or mask>; search
例如:
$ file = etc; 搜索
如果您使用的是CSH或TCSH,请使用以下解决方案:
( find . > files_and_folders ) >& /dev/null
如果要输出到终端:
( find . > /dev/tty ) >& /dev/null
find . 2>&1 > files_and_folders | grep -v 'Permission denied' >&2
?