zgrep (oder, glaube wir, grep mit dem Flag -Z) lässt Sie die komprimierten Dateien grep und ich denke, Sie werden viel darüber sagen, was Sie wollen, aber dies gibt Ihnen nicht den Dateinamen, ohne dass Sie etwas mehr mit der Header :(
Wie mache ich das Äquivalent von "grep etwas * -Rin" auf der Liste der tar.gz-Dateien?
Ich habe eine Reihe von tar.gz-Dateien und möchte einen "grep etwas * -Rin" machen, so wie ich es für sie tun würde, wenn sie nicht tar.gzed wären. Ich möchte, dass sie tar.gzed bleiben, wie sie sind, aber grep sie schnell und finde die Vorkommen meines grep mit dem vorangestellten Dateinamen und der Zeilennummer.
So etwas wie:
grep mytoken1 * .tar.gz -Rin
und etwas bekommen wie:
my1.tar.gz, dir1 / file2: 123: mytoken1 steht in dieser Zeile my2.tar.gz, dir2 / file3: 233: mytoken1 ist auch in dieser anderen Zeile [...]
Gibt es eine Möglichkeit, dies zu tun?
5 Antworten auf die Frage
- Beliebte
- Neu
- Mit Kommentaren
- Aktiv
Found in Unix script to search within a .tar or .gz file :
The script :
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
will respect file boundaries and report the file names. The | grep '\.txt
part can be adapted to your needs or dropped.
(-z
tells tar
it is gzip
compressed. -t
lists the contents. -x
extracts. -O
redirects to standard output rather than the file system. Older tar
s may not have the -O
or -z
flag, and will want the flags without -
: e.g. tar tz file.tar.gz
)
If your grep does not support these flags, then one can use 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 } }
This will not coalesce adjacent matches, unlike grep -B, and can thus repeat lines that are within 3 lines of two different matches.
Eine Möglichkeit wäre, diesen schnellen Hack zu verwenden:
#!/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 "# <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 "#,#:#:#" if regexp =~ l end end end end
Das heißt nicht, dass ich es für größere Archive empfehlen würde, da jede Datei aus dem Archiv in den Speicher gelesen wird (tatsächlich zweimal).
Wenn Sie eine etwas speichereffizientere Version wünschen, müssen Sie entweder eine andere Implementierung der e.read
Schleife vornehmen ... oder vielleicht eine andere Sprache insgesamt. ;)
Ich könnte es ein bisschen effizienter machen, wenn Sie wirklich interessiert sind ... aber es wird definitiv nicht mit C oder anderen kompilierten Sprachen verglichen, was die Rohgeschwindigkeit angeht.
Ich denke, das wird sehr knifflig.
Tatsächlich ist tar im Grunde eine Verkettung aller Include-Dateien mit Kopfzeilen. Im Grunde könnte eine grep-in-tar
Funktion geschrieben werden, die sich damit befasst und Informationen über die Datei- und Zeilennummer bereitstellt (einfaches grep mit Header-Lesen und Zeilennummer-Subtraktion). Ich habe von einem solchen Programm nichts gehört.
Das Problem ist mit GZIP. Dies ist ein Komprimierungsformat, das Sie dekomprimieren müssen, wenn Sie auf den Inhalt zugreifen möchten.
gunzip -c files.tgz | grep-in-tar
wäre eine Möglichkeit, das zu tun, was Sie wollen. Im Moment können Sie es versuchen, gunzip -c files.tgz | grep -Rin
aber es wird nur gesagt, dass die Binärdatei übereinstimmt.
The modular approach to *nix tools means that there's no simple way to do this efficiently with grep / tar / zcat. Ideally you want to decompress the files only once, and process each tar file in a single pass. Here's my attempt at 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),
Note: this doesn't do directory recursion (-R) or case-insensitvity (-i), or other options supported by GNU grep, but they wouldn't be tricky to add.
Verwandte Probleme
-
9
grep alle .java-Dateien in einem Verzeichnis für eine bestimmte Zeichenfolge
-
3
Kann GNU Grep eine ausgewählte Gruppe ausgeben?
-
5
Grep-Tool für XML
-
4
Wie kann ich bestimmte Dateien in einem Verzeichnis rekursiv anzeigen?
-
8
Linux grep oder Verwendung finden
-
4
Wozu benutzt man ? in grep befehl .. und praktischen einsatz
-
3
tar.gz programmatisch in einem einzigen Schritt (unter Windows mit 7zip) extrahieren
-
5
Erhalten Sie farbige Ergebnisse, wenn Sie ein Rohr von grep to less verwenden
-
6
grep für vista 64?
-
6
Linux: Inhalt der Unterverzeichnisse mit dem angegebenen Namen auflisten?