我需要搜索目录及其子目录中每个文件的前 50 行。
这将执行递归部分,但如何限制每个文件的前 50 行?
grep -r "matching string here" .
有些文件非常大,我只希望匹配前 50 行。我尝试通过不搜索某些文件中的兆字节二进制数据来加快此过程。
答案1
如果您只想要匹配的文件:
find . -type f -exec bash -c 'grep -q "matching string here" < <(head -n 50 "$1")' _ {} \; -printf '%p\n'
或者
find . -type f -exec bash -c 'grep -q "matching string here" < <(head -n 50 "$1") && printf '%s\n' "$1"' _ {} \;
如果您只想要匹配的字符串:
find . -type f -exec head -n 50 {} \; | grep "matching string here"
或更好,
find . -type f -exec head -q -n 50 {} + | grep "matching string here"
如果你想要两者:
find . -type f -exec bash -c 'mapfile -t a < <(head -n 50 "$1" | grep "matching string here"); printf "$1: %s\n" "${a[@]}"' _ {} \;
评论。
sed
用 代替组合可能会稍微容易一些head
--grep
。- 我要强调的是,对于可能包含奇怪符号(空格、换行符等)的文件名,所有三种方法都是 100% 安全的。
- 对于其中两种方法,我假设您有一个较新的 bash 版本。
- 您可以
-exec ... +
在每种方法中使用,但您必须自己编写内部循环!(留给读者的简单练习)。如果您有海量文件,这可能会稍微提高效率。
答案2
如果您需要与原始内容相同的 grep 输出,您可以执行以下操作:
find . -type f | while read f; do
if head -n 50 "$f"|grep -s "matching string here"; then
grep "matching string here" "$f" /dev/null
fi
done
如果您只需要文件名,则可以用 替换第二个 grep echo "$f"
。
答案3
您需要组合几个不同的实用程序才能获得所需的功能。使用该find
命令递归目录,查找所有文件并对head
找到的每个文件执行该命令。该head
命令可用于仅转储每个文件的前 50 行。最后,将输出通过管道传输到 grep 以搜索所需的字符串。
find . -type f -exec head -n 50 {} ";" | grep "matching string here"