我有多个子目录,每个子目录的深度都不同。我需要在特定文件类型(例如*.out
)中搜索字符串的最后一次出现。我该如何实现?
我努力了:
grep -r 'string' **/*.out | tail -1
但这只给了我最后一个文件的最后一个字符串。
答案1
假设您位于子目录的父目录中:
find . -type f -name '*.out' -exec sh -c '
for f do
grep "string" /dev/null "$f" | tail -n 1
done
' sh {} +
答案2
我会使用类似的东西:
for i in `find . -name "*.out" -type f`;
do
grep -l 'string' $i
grep 'string' $i|tail -1
done
使用第一个 grep,您将获得文件名和下面(第二个 grep)的内容。
只要文件名不包含空格或\[*?
.看cuonglm 的回答以获得强大的解决方案。
答案3
在zsh
GNU 系统上:
for f (**/*.out(.)) tac < $f | grep --label=$f -m1 string
答案4
使用gnu
工具,您可以使用一次调用gawk
:
awk '/pattern/{l=$0} ENDFILE{if (l) {print FILENAME ":" l; l=""}}' **/*.out
(如果行匹配,则将其存储到l
每个文件末尾的 ; 中,如果l
不为空,则打印文件名,l
然后重置l
)
或者sed
:
sed -ns '/pattern/h;${x;//{F;p}}' **/*.out
(如果行匹配,复制到h
旧空间;如果 la $
t 行,ex
更改保持空间 w.模式空间;如果匹配,则p
打印F
文件名和行)
尽管输出不同 - 文件名和相应的最后一个匹配行位于不同的位置线 - 但如果通过管道传输到另一个sed
例如
sed -ns '/pattern/h;${x;//{F;p}}' **/*.out |sed '$!N;s/\n/:/'
它将模拟grep
输出1。
上述假设巴什(第 4 节带shopt -s globstar
) 或桀骜。要包含隐藏文件,请添加shopt -s dotglob
(巴什) 或者setopt dotglob
(桀骜)。
1:只要这些文件名都不包含换行符。