有一個選項可以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
命令中。