我有一个包含 2000 多个文本文件的目录。我正在尝试制作一个脚本:
- 读取 IP 地址列表
ip.txt
- Cats 目录中的每个文件
- Greps 每个文件的 IP 地址
如果找到关键字,则将关键字和文件名回显到文件。
输出应该是这样的:
$ cat
results.txt
192.168.2.3 was found in 23233.txt
192.168.4.0 was found in 2323.txt
目前我有这个:
while read p; do
for filename in *.txt; do
if cat $filename | grep "$p"
then echo "$p" is "$filename" | tee result.txt
fi
done
done<ips.txt
然而,这也会将所有文件名回显到结果中。我怎样才能解决这个问题?
答案1
首先,cat
在不需要时不使用它来保存它。而不是:
cat haystack | grep needle
您可以简单地:
grep needle haystack
至于你的脚本:
> results.txt # start with a fresh file for every run
while read ip; do
grep "$ip" * | grep -Ev 'results\.txt|ips\.txt' >> results.txt
done < ips.txt
grep
-into-管道grep
用于防止将输入和输出文件中的条目添加到输出文件中。
如果你有无数的文件需要检查并且你得到了argument list too long
,我们可以使用一个工具,比如xargs
将我们的命令分成足够短的块,以便 shell 允许:
> results.txt # start with a fresh file for every run
while read ip; do
find . -type f -maxdepth 1 -not -name ips.txt -not -name results.txt -print0 | xargs -0 grep "$ip" >> results.txt
done < ips.txt
在这里,我们过滤掉了输入和输出文件,并使用逻辑输入find
,因此我们不再需要grep
输入grep
。
答案2
假设您的文件只有 IPv4 地址(没有 IPv6),您可以运行如下所示的命令:
find [dir1] -maxdepth 1 -type f -iname ip.txt -exec grep -H '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*' {} \;
这应该可以处理无限数量的文件。你的输出看起来像这样[dir1]/ip.txt:1.2.3.4
。当然,您需要将“[dir1]”替换为实际目录(或者您可以省略此选项,在这种情况下 find 将仅使用您当前的工作目录)。如果您愿意,您可以指定多个目录。事实上,对于可以在 find 命令中放入多少个目录,不应该有任何真正的限制,只要将它们放入即可前“-max深度”参数。
答案3
如果你不喜欢 grep 的话,另一种选择是我很久以前用来取代 grep 的最喜欢的工具 -确认。它几乎可以放入您提供的脚本中并提供您需要的输出。 (默认情况下它是递归搜索,如果您不想搜索子文件夹中的文件,则值得注意)。
while read p; do
for filename in $(ack -l $p); do
echo "$p found in $filename" >> results.txt
done
done<ips.txt