我需要隐藏以下所有拒绝权限的消息:
find . > files_and_folders
我正在尝试何时出现此类消息。 我需要收集所有不会出现的文件夹和文件。
是否可以将权限级别files_and_folders
到files_and_folders
文件?
如何同时隐藏错误?
#1楼
您还可以使用-perm
和-prune
谓词来避免进入不可读的目录(另请参见如何从查找程序中删除“ permission否认”的打印输出语句?-Unix&Linux Stack Exchange ):
find . -type d ! -perm -g+r,u+r,o+r -prune -o -print > files_and_folders
#2楼
采用:
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
! -readable
匹配不可读的目录(&file)。 -
-prune
操作不会进入目录。 -
! -readable -prune
! -readable -prune
可以转换为:如果目录不可读,则不要进入该目录。 - -
-readable
测试考虑了-perm
测试忽略的访问控制列表和其他权限伪像。
另请参见find
(1)联机帮助页 。
#3楼
为了避免仅获得权限拒绝警告,请通过搜索从修剪中删除不可读文件,以使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 这样的文件 并显示) 。
#4楼
采用
sudo find / -name file.txt
这很愚蠢(因为您提高了搜索范围)并且不安全,但是编写起来却短得多。
#5楼
尽管上述方法无法解决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$
find . -type f -name "your_pattern" -exec du -ch {} + 2>/dev/null | grep total$
。
这将返回给定模式的文件总大小。 注意find命令末尾的2>/dev/null
。
#6楼
注意:
*这个答案可能比用例需要的要深,并且find 2>/dev/null
在许多情况下可能已经足够了。对于跨平台的观点及其对某些高级Shell技术的讨论,尽管找到的情况可能是假设的,但仍可能会引起人们的兴趣,以便找到一种尽可能健壮的解决方案。
* 如果您的系统配置为显示本地化的错误消息 ,请在下面的find
调用前添加LC_ALL=C
( LC_ALL=C find ...
),以确保报告了英语消息,以便grep -v 'Permission denied'
按预期工作。但是,无论如何,任何确实显示的错误消息都将以英语显示。
如果您的shell是bash
或zsh
,那么有一种解决方案既健壮又相当简单 , 仅使用符合POSIX的find
功能 ; 尽管bash
本身不是POSIX的一部分,但大多数现代Unix平台都随附了它,这使得该解决方案具有广泛的可移植性:
find . > files_and_folders 2> >(grep -v 'Permission denied' >&2)
注意: grep
的某些输出在 find
完成后很可能会到达,因为整体命令不会等待>(...)
的命令完成。 在bash
,可以通过附加| cat
来防止这种情况| cat
| 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。无副作用 :
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
可以明确地对其进行操作。
唯一的缺点是整个退出代码将是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要求) ,该重定向 甚至可以使用将文件路径打印到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
,但是可以应用与上述相同的修复程序。
现有答案的注释:
关于Michael Brux的答案 ,有几点要注意
find . ! -readable -prune -o -print
find . ! -readable -prune -o -print
find . ! -readable -prune -o -print
:它需要GNU
find
; 值得注意的是,它不适用于macOS。 当然,如果您只需要使用该命令来使用GNUfind
,这对您就不会有问题。某些
Permission denied
错误可能仍会浮出水面:find ! -readable -prune
find ! -readable -prune
报告当前用户确实具有r
权限但缺乏x
(可执行)权限的目录子项的此类错误。 原因是因为目录本身是可读的,所以不会执行-prune
,并且尝试进入该目录会触发错误消息。 也就是说, 典型的情况是缺少r
许可。注意:以下几点是有关原理和/或特定用例的问题,您可能会决定它与您无关,并且该命令非常适合您的需求,尤其是仅打印路径就是您所做的一切时:
- 如果将允许拒绝的错误消息的过滤概念化,这是一个您希望能够应用于任何
find
命令的单独任务,那么主动预防允许被拒绝的错误的相反方法是在find
命令中引入“噪声”,即还介绍了复杂性和逻辑陷阱 。 - 例如,对Michael的回答(在撰写本文时),投票最多的评论试图显示如何通过包含
-name
过滤器来扩展命令,如下所示:find . ! -readable -prune -o -name '*.txt'
然而,这并不因为后工作打算,-print
需要采取行动(的解释中可以找到这个答案 )。 这样的微妙之处可能会引入错误。
- 如果将允许拒绝的错误消息的过滤概念化,这是一个您希望能够应用于任何
乔纳森·莱夫勒(Jonathan Leffler)的答案的第一个解决方案是
find . 2>/dev/null > files_and_folders
find . 2>/dev/null > files_and_folders
,正如他本人所言, 盲目地使所有错误消息find . 2>/dev/null > files_and_folders
(而且解决方法很麻烦,而且也不完全健壮,正如他还解释的那样)。 实用地说 ,这是最简单的解决方案 ,因为您可能会满意地假设所有错误都与权限相关。薄雾的答案 ,
sudo find . > files_and_folders
sudo find . > files_and_folders
简洁,务实,但出于安全考虑, 除了仅打印文件名外 , 不建议使用其他任何方法 :由于您以root用户身份运行,“您可能会因find或bug的混乱而使整个系统陷入混乱恶意版本,或不正确的调用会意外地写入内容,如果您以正常权限运行此文件,则不会发生”(摘自Tripleee关于Mist的回答的评论 )。Viraptor的答案中的第二个解决方案,
find . 2>&1 | grep -v 'Permission denied' > some_file
find . 2>&1 | grep -v 'Permission denied' > some_file
find . 2>&1 | grep -v 'Permission denied' > some_file
存在误报的风险(由于通过管道发送stdout和stderr的混合),并且有可能代替通过stderr报告非权限拒绝的错误,而是将它们捕获到输出文件中的输出路径。
#7楼
上面的答案对我都不起作用。 我在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脚本解决方案更改为:
很高兴找到/ home * / -maxdepth 5-关注\\
\\( -type d -a !\\(-可读-a-可执行\\) \\) -修剪 \\
-o \\
\\(-type d -a-可读-a-可执行-a -name“ $ {m_find_name}” \\)-print
此处的关键是为组合表达式放置“ not true”:
has read access AND has execute access
否则,它没有完全访问权限,这意味着:修剪它。 在以前建议的解决方案失败的一种情况下,这证明对我有用。
我在评论部分提供了以下技术详细信息。 如果细节过多,我深表歉意。
- ¿为什么使用命令nice? 我在这里有了主意。 最初,我认为在查看整个文件系统时降低进程优先级会很好。 我意识到这对我来说毫无意义,因为我的脚本仅限于几个目录。 我将-maxdepth减少到3。
- ¿为什么在/ home * /中搜索? 这与此线程无关。 我通过与非特权用户(不是root)一起编译的源代码手动安装所有应用程序。 它们安装在“ / home”中。 我可以同时存在多个二进制文件和版本。 我需要找到所有目录,以主从方式检查和备份。 我可以有多个“ / home”(专用服务器中运行着几个磁盘)。
- ¿为什么使用-follow? 用户可以创建指向目录的符号链接。 它的有用性取决于,我需要记录找到的绝对路径。
#8楼
简单答案:
find . > files_and_folders 2>&-
2>&-
关闭( -
)标准错误文件描述符( 2
),因此所有错误消息均被静音。
- 如果以其他方式显示“
Permission denied
”错误,则退出代码仍为1
对于GNU强大的答案find
:
find . -type d \\! \\( -readable -executable \\) -prune -print -o -print > files_and_folders
传递额外的选项以find
-prune
(防止降序进入),但仍-print
任何不具有( \\!
)同时具有- -readable
和- -executable
权限的目录( -type
d
),或者( -o
)- -print
任何其他文件。
-
-readable
和-executable
选项是GNU的扩展,而不是部分POSIX标准 - 仍可能在异常/损坏的文件上返回“
Permission denied
”(例如,请参见影响使用lxcfs
<v2.0.5的容器安装的文件系统的错误报告 )
适用于任何POSIX兼容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
使用环境变量 , 3>&2 2>&1 1>&3
和3>&2 2>&1
复制文件描述符设置POSIX语言 环境 ,以将标准错误流传grep
和[ $? = 1 ]
[ $? = 1 ]
使用[]
反转grep
返回的错误代码,以近似find
的原始行为。
- 还将过滤由于输出重定向而导致的任何
'Permission denied'
错误(例如,如果files_and_folders
文件本身不可写)
#9楼
您可以使用grep -v反向匹配
-v, --invert-match select non-matching lines
像这样:
find . > files_and_folders
cat files_and_folders | grep -v "permission denied" > files_and_folders
应该去魔术
#10楼
您也是将查找结果保存在文件中的简单解决方案。
找 。 -名称'NameOfSearchedFile'>> results.txt
#11楼
-=对于MacOS =-
使用别名创建新命令:只需添加〜/ .bash_profile行:
alias search='find / -name $file 2>/dev/null'
在新的“终端”窗口中,您可以调用它:
$ file=<filename or mask>; search
例如:
$ file = etc; 搜索
#12楼
如果您使用的是CSH或TCSH,请使用以下解决方案:
( find . > files_and_folders ) >& /dev/null
如果要输出到终端:
( find . > /dev/tty ) >& /dev/null
但是, 如“ csh-whynot”常见问题解答所述,您不应使用CSH。
#13楼
采用:
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兼容版本的find
任何Unix变体上运行。
如果您希望适应系统上使用的find
的特定版本,则可能有其他选择。 特别是GNU find
有许多其他版本中没有的选项-请参阅当前接受的答案中的一组这样的选项。
#14楼
重定向标准错误。 例如,如果您在UNIX机器上使用bash,则可以将标准错误重定向到/ dev / null,如下所示:
find . 2>/dev/null >files_and_folders
#15楼
管stderr
到/dev/null
通过使用2>的/ dev / null的
find . -name '...' 2>/dev/null
#16楼
这些错误将打印到标准错误输出(fd 2)。 要过滤掉它们,只需将所有错误重定向到/ dev / null即可:
find . 2>/dev/null > some_file
或先加入stderr和stdout,然后grep删除那些特定的错误:
find . 2>&1 | grep -v 'Permission denied' > some_file
#17楼
我不得不使用:
find / -name expect 2>/dev/null
指定我要查找的名称,然后告诉它将所有错误重定向到/ dev / null
期望是我正在搜索的期望程序的位置。
#18楼
如果要从根“ /”开始搜索,则可能会看到类似以下的输出:
find: /./proc/1731/fdinfo: Permission denied
find: /./proc/2032/task/2032/fd: Permission denied
是因为允许。 要解决这个问题:
您可以使用sudo命令:
sudo find /. -name 'toBeSearched.file'
sudo find /. -name 'toBeSearched.file'
。 它询问超级用户的密码,当输入密码时,您将看到您真正想要的结果。您可以使用将“标准错误输出”从(通常是显示/屏幕)重定向到某些文件,并避免在屏幕上看到错误消息! 重定向到特殊文件/ dev / null:
find /. -name 'toBeSearched.file' 2>/dev/null
您可以使用将标准错误输出从(通常显示/屏幕)重定向到标准输出(通常显示/屏幕),然后使用带有-v“ invert”参数的grep命令进行管道处理,以不显示具有“权限被拒绝”的输出行单词对:
find /. -name 'toBeSearched.file' 2>&1 | grep -v 'Permission denied'