我有一个目录,其中包含 3 个命名管道以及其他文件:FIFO、FIFO1 和 FIFO11。如果我尝试类似
grep mypattern *
在这个目录中,grep 永远挂在命名管道上,所以我需要排除它们。不料,
grep --exclude='FIF*' mypattern *
不能解决问题;grep 仍然永远挂起。然而,
grep -r --exclude='FIF*' mypattern .
确实解决了挂起问题(尽管搜索所有子目录的不良副作用)。
我做了一些测试,表明grep --exclude ='FIF*' mypattern *
如果 FIFO 等是常规文件,而不是命名管道,则可以按预期工作。
问题:
- 如果它们是常规文件,为什么在这两种情况下都
grep
跳过,并在递归情况下跳过命名管道,但在非递归情况下不跳过命名管道?--excludes
--excluded
- 是否有另一种方式来格式化排除在所有情况下都会跳过这些文件?
- 有没有更好的方法来完成我所追求的?(编辑:我刚刚
--devices=skip
在 grep 中发现了这个标志,所以这就是这部分的答案......但我仍然对问题的前两部分感到好奇)
即使正则表达式告诉它跳过它们,它似乎
grep
仍然会打开文件:(注意:这些都没有读取权限。)
授予读取权限,如果它们被排除在外,它似乎不会在打开后尝试读取它们:
并且由于
openat
没有用 调用O_NONBLOCK
,因此开口本身挂起,并且 grep 没有到达将其排除在读取之外的部分。看源码,相信流程是这样的:
grep_command_line_arg
每个文件。grepfile
如果不在标准输入上,那会调用。grepfile
打开文件后调用。grepdesc
grepdesc
检查排除文件。递归时:
grepdirent
在调用之前检查是否排除了文件grepfile
,因此永远不会发生失败openat
。为什么不与“查找”结合使用?获取文件列表并 grep 进入它们: