我需要在整个文件系统中找到给定字符串的所有实例,因为我不记得将它放在哪个配置文件、脚本或任何其他程序中,并且我需要用新的字符串更新该字符串。
我尝试使用以下命令
`grep -nr'needle'/--exclude-dir=.svn|邮件[电子邮件保护]-s ‘xxx 上的参考资料’
如果我在一个小的目录上运行此命令,它会以以下形式提供我需要的输出
/path1/:nn:line containing needle
/path2/:nn:line containing needle
其中 /path1 是文件的完整路径,nn 是包含针的行,最后一个字段是该行的内容。
但是,当我在根目录上运行命令时,grep 进程会在一段时间后挂起。我大约 8 小时前运行了这个脚本,即使在一个较小的文件系统(小于 5GB)上,它也不会结束,如果我运行top
或ps
进程似乎处于休眠状态
root 24909 0.0 0.1 3772 1520 pts/1 S+ Feb10 0:15 grep -nr needle / --exclude-dir=.svn
为什么它没有结束?有没有更好的方法可以做到这一点(这是一次性的工作,我不需要多次执行)
谢谢。
更新:我找到了一个使用 find 和 xargs 的解决方案,它似乎有效,并且比 find -exec 解决方案占用更少的系统资源。这是我的最终命令行:
find /{boot,etc,home,lib,lost+found,opt,root,sbin,usr,var} -type f -print0 | xargs -r0 grep -nr 'needle' | mail [email protected] -s 'References on xxx'
我使用这种/{dir1,dir2,...,dirn}
语法是因为我想要包含前导斜杠的完整路径的输出行,这样您就可以cd /
在任何目录中使用该命令而无需 ie。
答案1
文件系统中有些文件不是真正的文件,而是内核的钩子。其中一些文件可以永久读取。尝试
grep foo /dev/zero
看看它的实际作用。在它接管整个系统之前,准备好使用 ctrl-C 停止它。
如果我想做你正在做的事情,我会列举/
我想要扫描的子目录,并确保我只检查文本文件,可能使用
cd /
find boot etc home lib lost+found media mnt opt root sbin tmp usr var -type f -exec grep needle {} /dev/null \;
注意列表是如何做的不是包含/dev
、/proc
或。/sys
/selinux
答案2
您可以尝试使用 find + xargs + grep 来实现这一点:
find /there -type f :MaybeSomeRestrictingFlagsLikeSizeNotBigger500MB_or_FS_type_if_u_know_its_exactly_on_EXT3_AndSoOn: -print0 | xargs -0r grep needle /dev/null
(即使只找到一个文件,/dev/null 也会使 grep 打印文件名)
答案3
我不知道为什么它没有结束,但“fgrep -R”通常在这些情况下有效。
答案4
正如其他人指出的那样,出现此错误的原因是您在一些会产生奇怪结果的“文件”上使用 grep。例如,grep XXX /dev/zero 将永远持续下去。
我首先会从搜索中排除 /dev/ 和 /proc/ 等目录。另一种方法是仅搜索“文件”,而不搜索其他类型。
此外,如果 grep 中的参数列表太长,您将收到此错误:
bash: /bin/grep: Argument list too long
您可以使用循环来解决这个问题,例如:
for i in `find -type f /`; do grep -H "sample string" $i; done
或者通过从 find 中执行,随你便。
find / -type f -exec grep -H "sample string" '{}' \; -print
这应该会先执行 find,然后 grep 每个文件。尽管有些人指出,每次找到文件时都生成 grep 效率很低,但您必须做一些“低效”的事情,因为您确实必须在每个文件中搜索该字符串。