如何将 find 和 grep 与循环和变量一起使用?

如何将 find 和 grep 与循环和变量一起使用?

我的目录中有一堆文件。

# ls -1
file1
file2
file3
file4
file5
file6
file7
file8
file9
file10

任务是查找早于file5.我可以这样做

# find . ! -newer file5
./file1
./file2
./file3
./file4
./file5

现在我有一个文件,其中对上述任何/所有内容的引用可能类似于

# logfile=log
cat ${logfile}
/var/log/app/file1
/var/log/app/file3
/var/log/app/file5

现在我只想要那些早于 file5 且也在日志文件中的文件的列表。所以结果列表将是:

file1
file3
file5

我尝试像这样从这些文件名中查找文件名,但它不起作用。

find . ! -newer file4 -exec bash -c 'for i in {}; do grep $i ${logfile}; done' \;

答案1

如果目录是/var/log/app然后而不是find . ! -newer file5运行find /var/log/app ! -newer /var/log/app/file5。这样, 的输出find将采用log.

find然后您可以仅使用一个过滤输出grep

find /var/log/app ! -newer /var/log/app/file5 | grep -xFf log

-x导致grep匹配整行;-F告诉它将模式视为固定字符串;-f从指定文件中读取模式。这些选项是可移植的。

或者(或者在当前工作目录不是/var/log/app,但您想假装它是的情况下)创建第二个日志,因此其中的条目与./…原始工作目录的一般格式匹配find

sed 's|^/var/log/app/|./|' log > log2

新日志包含可用于过滤原始find命令输出的相对路径:

find . ! -newer file5 | grep -xFf log2

笔记:

  • ! -newer file5并不意味着“比file5”更老。此测试匹配file5任何同样旧的文件。
  • 附加选项/测试(例如-maxdepth 1-type f)可能有用。

你的尝试:

find . ! -newer file5 -exec bash -c 'for i in {}; do grep $i ${logfile}; done' \;

在许多方面都有缺陷或次优:

  • 您将日志文件视为数据,将路径名视为find模式。如上所示,反之亦然更容易。
  • 在内部的上下文中bash$i${logfile}不被引用。它们应该用双引号引起来
  • 您嵌入{}了 shell 代码。一般来说,嵌入的{}行为就像一个不带引号的变量,但无论你如何引用它,都有命令注入漏洞。所以情况更糟。
  • 您使用了-exec … \;which 替换了{}一个路径名(而不是-exec … {} +),但您仍然写得for i in {}好像您期望有很多路径名一样。一般来说,内壳可能会将其所代替的内容解释为{}多个单词。文件名生成也可能被触发。这就是上面提到的“像一个不带引号的变量”行为。因此,一般来说,您可能会得到许多循环的“路径名”,但不是您所期望的。
  • logfile不在环境中,因此内壳将扩展$logfile为空字符串。您不希望外壳扩展它(使其与嵌入有类似的缺陷{})。

相关内容