![](/img/trans.png)
[英]Shell script use find command to get list of files in order of directory files first and then sub directory and so on
[英]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.