我在 while 循环中使用 find 。它获取 ip.txt 中的 IP 列表,在文件目录中搜索 IP,然后将找到的每个 IP 的文件名写入名为 results.res 的文件中
我想在每次成功找到后停止并移动到下一个IP。
我当前的脚本是:
while read ip; do
find . -type f -maxdepth 1 -not -name ips.txt -not -name results.res -print0 | xargs -0 grep "$ip" >> results.res
done < ips.txt
我研究了网站上的其他答案,发现使用
-print -quit
-print | head -n 1
在第一次成功找到后停止查找,但是因为我使用的是 while 循环,所以这不起作用,有人可以建议一个可行的解决方案吗?
答案1
while IFS= read -r ip; do
find . -maxdepth 1 \
-type f \
! -name ips.txt \
! -name results.res \
-exec grep -lwFe "$ip" {} \; \
-quit
done < ips.txt > results.res
将文件的每一行读ips.txt
入$ip
变量并浏览匹配条件的文件find
(无特定顺序),报告包含$ip
固定F
字符串和w
ord 分隔的第一个文件。当成功-quit
时调用-exec
,即grep
返回一个真的找到匹配项时退出状态。
答案2
按照当前编写脚本的方式,它将运行find
,然后运行它找到的每个文件,以及它在 中找到的grep
每个文件。 ip
ips.txt
您不需要find
每次都运行来获取相同的文件列表,因此将其从while
循环中取出并将其分配给一个变量。您也不需要grep
为找到的每个文件都运行,您可以通过一个命令搜索所有文件。现在您已经有了文件列表,您可以grep
为每个文件执行 aip
并仅返回第一个匹配项。所以脚本现在看起来像这样:
files=$(find . -maxdepth 1 -type f -not -name ips.txt -not -name results.res)
while read ip; do
grep --with-filename --max-count=1 "$ip" $files | head -n 1 >> results.res
done < ips.txt
这将grep
遍历每个infind
命令中的每个文件,并且应将包含每个 IP 地址的行以及在其中找到它的第一个文件放入. ip
ips.txt
results.res
编辑:
经过一些测试,似乎确实有更好的方法,因为前面的代码根本不处理带有空格或奇数字符的文件名。所以我要摆脱它,find
因为这里似乎没有必要。
您计划grep
遍历当前目录中除results.res
和 之外的所有文件ips.txt
,因此您可以使用grep
而不查找:
while read ip; do
grep --with-filename --max-count=1 --exclude={results.res,ips.txt} "$ip" * | head -n 1 >> results.res
done < ips.txt