Bash

如何將 find 和 grep 與循環和變數一起使用?

  • September 30, 2021

我在一個目錄中有一堆文件。

# 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' \;

如果目錄是/var/log/appthen 而不是find . ! -newer file5run 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視為模式。如上所示,以相反的方式執行此操作要容易得多。
  • 在 inner 的上下文中bash$i${logfile}沒有被引用。它們應該被雙引號
  • 您嵌入{}了 shell 程式碼。一般來說,嵌入式{}可以表現得像一個未引用的變數,但無論你如何引用它,都存在命令注入漏洞。所以情況更糟。
  • 您使用-exec … \;which 替換{}為一個路徑名(而不是-exec … {} +),但您仍然寫得for i in {}好像您期望很多一樣。通常,內殼可能會將其代替的內容解釋{}為多個單詞。也可以觸發文件名生成。這是上面提到的“就像一個未引用的變數”行為。所以一般來說,你可能會得到很多循環的“路徑名”,而不是你所期望的。
  • logfile不在環境中,因此內殼將擴展$logfile為空字元串。您不希望外殼擴展它(使其具有與 embedding 類似的缺陷{})。

引用自:https://unix.stackexchange.com/questions/671256