使用 find 指令從檔案中搜尋多個模式

使用 find 指令從檔案中搜尋多個模式

有一個選項可以grep -f MY_FILE讓它搜尋從檔案中取得的模式,而不是直接在命令列上指定。

是否有一個選項可以對命令執行類似的操作find並讓它讀取模式以從輸入檔案中進行搜尋?

答案1

find似乎沒有內建這樣的功能,但您可以使用檔案中的參數來xargs建構多個命令,例如:find

xargs -a patterns.txt -I% find Pictures/ -name %

其中patterns.txt是適合過濾器的模式列表-name,每行一個模式。請注意,其中沒有前導/尾隨空格,因為它們將包含在模式中。一個例子:

*.jpg
2018-06-*
*foo*
unicorn.png

筆記:雖然這個答案看起來非常簡單和優雅,但它在評論中正確指出它有一些缺點:

對於大型資料夾或許多模式來說,效能不太好,因為它將find在檔案中的每個模式運行一次,導致它重複掃描整個搜尋資料夾。

因此,如果您有多個可能重疊的模式(例如*.jpg*foo*),則符合多個模式的檔案將在結果中出現多次。如果您只是列印名稱,則可以透過管道傳輸輸出sort -u以刪除重複項,但如果您刪除這些結果或-exec對它們執行任何命令,這可能更不可取。

如果這些缺點中的任何一個對您的用例來說是一個問題,也許最好選擇一個替代答案。

命令解釋:

  • xargs將讀取參數列表並使用它們來建構和運行新的命令列。
  • -a patterns.txt告訴它從該文件而不是標準輸入中讀取。
  • -I%告訴它不要簡單地將讀取的參數附加到命令列末尾,而是用%一個參數替換您提供的命令列中的字元。這意味著為每個輸入參數建立並運行一個單獨的命令。
  • find Pictures/ -name %是我們要插入參數的命令行,將%.您不需要在這裡引用,因為xargs會注意它插入的每個參數都將被視為單一標記,並且不會自行拆分。您當然可以Pictures/用自己的搜尋目錄替換 ,也可以使用不同的和/或更多的過濾器,而不僅僅是-name.因為我們使用插入選項,所以您也可以將操作附加-exec ...到命令末尾。

答案2

您可以簡單地使用文件內容建立正規表示式paste -sd'|' bar

find ~/foo -regextype egrep -regex "^.*/($(paste -sd'|' bar))$"

正規表示式將是"^.*/(a|b)$"

答案3

不久前,我做了一個回答-regex使用中的標誌組合多個模式find。基於此,我們可以製作一個小腳本或函數來完成相同的工作,但從文件中建立模式清單。

#!/bin/bash

read_file(){
    local full_pattern=""
    while IFS= read -r pattern; do
        if [ -z "$full_pattern"  ];then
            full_pattern="$pattern"
            continue
        fi
        full_pattern="$full_pattern\|$pattern"
    done < "$1"
    echo "$full_pattern"
}

fp=$(read_file "$1" )
find "$2" -type f -regex ".*\($fp\).*$" 

這是做什麼的:

  • 我們將腳本稱為findf.sh input.txt /etc,其中第一個位置參數是帶有模式的文件,第二個是要搜尋的目錄。.如果省略目錄參數,GNU find 會假定目錄,因此$2不需要。
  • 該函數read_file讀取輸入文件,該文件是腳本的第一個位置參數。這建立了標誌的模式-regex
  • 此模式會回顯到腳本的「主」區塊,並儲存到fp變數中,然後傳遞到find命令中。

相關內容