題 如何在tar.gz文件列表中執行相當於“grep something * -Rin”的操作?


我有一堆tar.gz文件,我想做一個“grep something * -Rin”,如果它們沒有tar.gzed那麼就像我一樣。我想讓它們保持原樣,但是它們會動態地在它們上面查找我的grep並帶有前綴文件和行號。

就像是:

grep mytoken1 * .tar.gz -Rin

得到類似的東西:

my1.tar.gz,dir1 / file2:123:mytoken1在這一行
my2.tar.gz,dir2 / file3:233:mytoken1也在另一行
[...]

有辦法做到這一點嗎?


5
2018-06-08 09:20


起源




答案:


zgrep(或者,我們相信,使用-Z標誌的grep)會讓你grep壓縮文件,我想會告訴你你想要什麼,但這並沒有給你文件名,沒有更多的工作看著標題:(


5
2018-01-31 06:50



nsc.ru/cgi-bin/www/unix_help/unix-man?zgrep+1 根據這個zgrep與-p標誌的grep相同(需要zlib編譯,tho),我沒有在我面前的終端,但我認為這會起作用。 - SW.
臉紅 就像我發現ls和l一樣。我覺得自己長大了...... - Joe
+1 zgrep應該像 tar 格式包含 逐字 文件內容的副本,加上一些標題信息和填充字節。 - Mr Shunz
這不會顯示存檔中找到模式的文件。 - harrymc
已編輯了評論中的信息。 - Joe


在發現 用於在.tar或.gz文件中搜索的Unix腳本 :

劇本 :

for file in $(tar -tzf file.tar.gz | grep '\.txt'); do 
    tar -Oxzf file.tar.gz "$file" | grep -B 3 --label="$file" -H "string-or-regex"
done

將尊重文件邊界並報告文件名。該 | grep '\.txt 部分可以適應您的需要或下降。

-z 告訴 tar 它是 gzip 壓縮。 -t 列出內容。 -x 提取物。 -O 重定向到標準輸出而不是文件系統。年長 tar可能沒有 -O 要么 -z 標誌,並希望沒有標誌 -:例如 tar tz file.tar.gz

如果你的grep不支持這些標誌,那麼可以使用awk:

#!/usr/bin/awk -f
BEGIN { context=3; }
{ add_buffer($0) }
/pattern/ { print_buffer() }
function add_buffer(line)
{
    buffer[NR % context]=line
}
function print_buffer()
{
    for(i = max(1, NR-context+1); i <= NR; i++) {
        print buffer[i % context]
    }
}
function max(a,b)
{
    if (a > b) { return a } else { return b }
}

與grep -B不同,這不會合併相鄰的匹配,因此可以重複這些行 在兩個不同的比賽的3行內。


4
2018-01-31 08:50





一種方法是使用這個快速黑客:

#!/usr/bin/ruby

=begin
Quick-and-dirty way to grep in *.tar.gz archives

Assumption:
    each and every file read from any of the supplied tar archives
    will fit into memory. If not, the data reading has to be rewritten
    (a proxy that reads line-by-line would have to be inserted)
=end

require 'rubygems'
gem 'minitar'
require 'zlib'
require 'archive/tar/minitar'

if ARGV.size < 2
    STDERR.puts "#{File.basename($0)} <regexp> <file>+"
    exit 1
end

regexp = Regexp.new(ARGV.shift, Regexp::IGNORECASE)

for file in ARGV
    zr = Zlib::GzipReader.new(File.open(file, 'rb'))
    Archive::Tar::Minitar::Reader.new(zr).each do |e|
        next unless e.file?
        data = e.read
        if regexp =~ data
            data.split(/\n/).each_with_index do |l, i|
                puts "#{file},#{e.full_name}:#{i+1}:#{l}" if regexp =~ l
            end
        end
    end
end

這並不是說我推薦它用於更大的檔案,因為檔案中的每個文件都被讀入內存(實際上是兩次)。

如果你想要更高效的內存版本,你要么必須採用不同的實現方式 e.read 循環...或者,或許,完全使用不同的語言。 ;)

如果你真的感興趣的話,我可以讓它更有效率......但就原始速度而言,它肯定不會與C或其他編譯語言相比。


2
2018-02-06 01:28



我應該使用哪個版本的紅寶石? $ ruby​​ ./tar_search.rb DSM 1.tar.gz 2.tar.gz /usr/lib/ruby/1.9.1/rubygems.rb:762:in report_activate_error': Could not find RubyGem minitar (>= 0) (Gem::LoadError) from /usr/lib/ruby/1.9.1/rubygems.rb:219:in 激活'from /usr/lib/ruby/1.9.1/rubygems.rb:1065:in gem' from ./tar_search.rb:13:in <主>' - 719016
我是在1.8.7開發的。但是,主要問題是缺少寶石 minitar。從shell中糾正: gem install minitar;那它應該工作。此外,Ruby 1.9.1工作正常(在gem安裝之後)。 - Wejn


我認為這將非常棘手。

事實上,tar基本上是所有包含文件的串聯,並添加了標題。基本上是一個 grep-in-tar 可以編寫函數來處理它並提供有關文件和行號的信息(帶有標題讀取和行號減法的基本grep)。我沒有聽說過這樣的節目。

問題出在gzip上。這是一種壓縮格式,因此如果要訪問內容,則需要對其進行解壓縮。

gunzip -c files.tgz | grep-in-tar

將是一種做你想要的方式。 目前你可以試試 gunzip -c files.tgz | grep -Rin 但它只會說二進製文件匹配。


0
2018-06-08 09:40





* nix工具的模塊化方法意味著沒有簡單的方法可以有效地使用grep / tar / zcat。理想情況下,您只想將文件解壓縮一次,並在一次傳遞中處理每個tar文件。這是我的嘗試 TGZ-的grep

#!/usr/bin/python
import re,sys,tarfile

exp=re.compile(sys.argv[1])
tarfiles=sys.argv[2:]

for tfile in tarfiles:
  tar=tarfile.open(tfile, mode='r|gz')
  for file in tar:
    name=file.name
    count=0
    for line in tar.extractfile(file):
      count += 1
      if exp.search(line):
        print "%s,%s:%d:%s" % (tfile, name, count, line),

注意:這不會執行目錄遞歸(-R)或大小寫不敏感(-i),或GNU grep支持的其他選項,但添加它們並不棘手。


0
2018-02-06 23:45