2014-10-28 26 views
1

除了使用tar tf以外,是否有更有效的方法來執行此操作,並根據所查找的文件檢查每個文件的輸出?找到一個文件是否存在於一些gzipped tarballs中的最快方法?

這是我做的,現在的方式,但它的速度很慢(大約有600-1000檔案是符合search_patterns):

ARRAY=() 
ARRAY[0]=/path/to/archives/*search_pattern1* 
ARRAY[1]=/path/to/archives/*search_pattern2* 
ARRAY[2]=/path/to/archives/*search_pattern3* 

for f in ${ARRAY[@]} 
do 
    if [[ $f =~ "matching_pattern1" ]]; then 
     if tar -tf "$f" | grep "matching_pattern2" ; then 
      printf "%s\n" $f; 
      exit 0; 
     fi 
    fi 
done 

對於它的價值,我search_patterns是連續3天,我希望首先找到與matching_pattern1匹配的檔案,然後查看所有這些檔案的matching_pattern2並輸出包含它的tar文件。

+0

你有一個文本文件名稱或文件glob(用於tarball中的文件)? – 2014-10-28 17:43:08

+0

你可能最好不要將globes粘在單個數組索引上,而是讓globs直接填充數組索引。 'arr =(/ path/to/archives/* search_pattern1 */path/to/archives/* search_pattern2 */path/to/archives/* search_pattern3 *)''。 – 2014-10-28 17:47:33

+0

@EtanReisner它也是一個glob – confused00 2014-10-28 17:47:52

回答

2

不會有太多的捷徑,tar文件在本質上是連續的,你能做的最好的是(多個文件,並可能在parallel)處理每個tar文件最多一次。隨着GNU tar搜索tar文件時,你可以這樣做:

tar --wildcards -tzf file.tgz pattern [pattern...] 
parallel -tk --tag tar --wildcards -tzvf ::: file*.tgz ::: "pattern" 

使用多種模式,匹配的文件名會顯示出來,並退出代碼0,如果發現任何。請記住使用「**」作爲glob來匹配不同的目錄。

但是,如果您只是在每個tar文件中查找單個模式,這實際上不會比現有方法快得多。 GNU tar對可搜索的tar文件進行了優化,但壓縮將抵消任何好處。 Tar文件可以是增量式,分割式,更新式,甚至包含同一文件的多個副本,除了掃描整個文件(即使大多數tar文件並不那麼複雜),沒有其他選擇。

如果這是一個經常性的任務,你可能會檔案被創建時考慮保留一個索引文件:

tar -czvf file.tgz files [...] > file.idx 

,或者如果您使用GNU tar,添加:--index-file=file.idx而是一個-v是文件名而已,與-vv索引文件將包含完整的詳細信息,如-tv所示。 (似乎沒有要在這個時候--index-file0 NUL分隔的選項。)

(如果它是有用的,也有替代tar這一點,見https://serverfault.com/questions/59795/is-there-a-smarter-tar-or-cpio-out-there-for-efficiently-retrieving-a-file-store

2

如果是一次性操作,並且您有常規tar文件(不是gzipped),我會建議使用strings從tar文件中提取所有ASCII字符串,使用grep檢查輸出,並僅解壓那些文件輸出符合你的模式。文件名保存在明文所以strings可能會拿給你:

$ strings file.tar | grep test 
test 
test.c 
test.c 
test.js 
test.pl 

strings可能工作略高於tar tf更快。

+0

我明白了。不幸的是,這些文件也是gzipped,我忘記把它放在OP – confused00 2014-10-28 17:48:34

+0

然後我不認爲有一個更快的方式來做到這一點。如果您有多臺計算機和一個快速網絡,請考慮在具有不同文件集的多臺計算機上並行執行此操作:) – afenster 2014-10-28 17:49:47

1

你正在依靠在for循環中的單詞分割。這不是一個好主意(對於命名不正常的文件並不安全)。你最好讓球體直接填充陣列。

arr=(/path/to/archives/*search_pattern1* /path/to/archives/*search_pattern2* /path/to/archives/*search_pattern3*) 

並使用for f in "${arr[@]}"

那麼這樣的事情可能工作(這可能是有文件,如果它是一個靜態的文件名字,但水珠總是要掃描整個壓縮包tar包快很多)。

for f in "${arr[@]}"; do 
    if tar -tf "$f" "matching_glob" &>/dev/null; do 
     echo "File found in $f" 
    fi 
done 
相關問題