簡體   English   中英

Shell:在目錄下的列表中查找文件

[英]Shell: find files in a list under a directory

我有一個包含約1000個文件名的列表,可在目錄及其子目錄下進行搜索。 有數百個具有超過1,000,000個文件的子目錄。 以下命令將運行find 1000次:

cat filelist.txt | while read f; do find /dir -name $f; done

有更快的方法嗎?

如果filelist.txt每行只有一個文件名:

find /dir | grep -f <(sed 's@^@/@; s/$/$/; s/\([\.[\*]\|\]\)/\\\1/g' filelist.txt)

-f選項表示grep搜索給定文件中的所有模式。)

<(sed 's@^@/@; s/$/$/; s/\\([\\.[\\*]\\|\\]\\)/\\\\\\1/g' filelist.txt)

<( ... )稱為過程替換 ,它與$( ... )有點相似。 這種情況是等效的(但是使用流程替換更整潔,可能更快一些):

sed 's@^@/@; s/$/$/; s/\([\.[\*]\|\]\)/\\\1/g' filelist.txt > processed_filelist.txt
find /dir | grep -f processed_filelist.txt

sed的調用在filelist.txt每一行上運行命令s@^@/@s/$/$/s/\\([\\.[\\*]\\|\\]\\)/\\\\\\1/g filelist.txt並將其打印出來。 這些命令將文件名轉換為與grep更好地兼容的格式。

  • s@^@/@表示在每個文件名之前加一個/ ^表示正則表達式中的“行首”)
  • s/$/$/表示將$放在每個文件名的末尾。 (第一個$表示“行尾”,第二個只是文字$ ,然后由grep解釋為“行尾”)。

這兩個規則的組合意味着grep將僅查找.../<filename>匹配./a.txt.backup ,因此a.txt./a.txt.backup./abba.txt不匹配。

s/\\([\\.[\\*]\\|\\]\\)/\\\\\\1/g在每次出現之前放置一個\\ . [ ]* Grep使用正則表達式,這些字符被認為是特殊字符,但是我們希望它們是普通字符,因此我們需要對其進行轉義(如果不對它們進行轉義,那么a.txt類的文件名將與abtxt類的文件匹配)。

舉個例子:

$ cat filelist.txt
file1.txt
file2.txt
blah[2012].txt
blah[2011].txt
lastfile

$ sed 's@^@/@; s/$/$/; s/\([\.[\*]\|\]\)/\\\1/g' filelist.txt
/file1\.txt$
/file2\.txt$
/blah\[2012\]\.txt$
/blah\[2011\]\.txt$
/lastfile$

然后,Grep在搜索find的輸出時,將該輸出的每一行用作模式。

如果filelist.txt是普通列表:

$ find /dir | grep -F -f filelist.txt

如果filelist.txt是模式列表:

$ find /dir | grep -f filelist.txt

使用xargs(1)可以使while循環比bash快一點。

像這樣

xargs -a filelist.txt -I filename find /dir -name filename

請注意,如果filelist.txt中的文件名包含空格,請閱讀xargs(1)聯機幫助頁xargs(1)部分中的第二段有關此問題的信息。

基於某些假設的改進。 例如,a.txt在filelist.txt中,並且您可以確保/ dir中只有一個a.txt。 然后,您可以告訴find(1)在找到實例時提早退出。

xargs -a filelist.txt -I filename find /dir -name filename -print -quit

另一個解決方案。 您可以對filelist.txt進行預處理,使其像這樣進入find(1)參數列表。 這將減少find(1)調用:

find /dir -name 'a.txt' -or -name 'b.txt' -or -name 'c.txt'

我不是很確定這里的問題,但是在嘗試找到一種方法來發現13000個文件中有4個未能復制后,我來到了此頁面。

沒有一個答案對我有用,所以我這樣做了:

cp file-list file-list2
find dir/ >> file-list2
sort file-list2 | uniq -u

結果是列出了我需要的4個文件。

這個想法是結合兩個文件列表來確定唯一的條目。 sort用於使重復的條目彼此相鄰,這是uniq過濾掉它們的唯一方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM