Tìm tệp có chứa nhiều từ khóa ở bất cứ đâu trong tệp


16

Tôi đang tìm cách liệt kê tất cả các tệp trong một thư mục chứa toàn bộ từ khóa tôi đang tìm kiếm, ở bất cứ đâu trong tệp.

Vì vậy, các từ khóa không cần phải xuất hiện trên cùng một dòng.

Một cách để làm điều này sẽ là:

grep -l one $(grep -l two $(grep -l three *))

Ba từ khóa chỉ là một ví dụ, nó cũng có thể là hai hoặc bốn, v.v.

Cách thứ hai tôi có thể nghĩ đến là:

grep -l one * | xargs grep -l two | xargs grep -l three

Phương pháp thứ ba, xuất hiện trong một câu hỏi khác , sẽ là:

find . -type f \
  -exec grep -q one {} \; -a \
  -exec grep -q two {} \; -a \
  -exec grep -q three {} \; -a -print

Nhưng đó chắc chắn không phải là hướng tôi sẽ đến đây. Tôi muốn cái gì mà đòi hỏi ít đánh máy, và có thể chỉ là một lời kêu gọi grep, awk, perlhoặc tương đương.

Ví dụ: tôi thích cách awkcho phép bạn khớp các dòng có chứa tất cả các từ khóa , như:

awk '/one/ && /two/ && /three/' *

Hoặc, chỉ in tên tệp:

awk '/one/ && /two/ && /three/ { print FILENAME ; nextfile }' *

Nhưng tôi muốn tìm các tệp trong đó các từ khóa có thể ở bất kỳ đâu trong tệp, không nhất thiết phải trên cùng một dòng.


Các giải pháp ưa thích sẽ thân thiện với gzip, ví dụ grepzgrepbiến thể hoạt động trên các tệp nén. Tại sao tôi đề cập đến điều này, là một số giải pháp có thể không hoạt động tốt do hạn chế này. Ví dụ: trong awkví dụ về in các tệp phù hợp, bạn không thể thực hiện:

zcat * | awk '/pattern/ {print FILENAME; nextfile}'

Bạn cần thay đổi đáng kể lệnh, thành một cái gì đó như:

for f in *; do zcat $f | awk -v F=$f '/pattern/ { print F; nextfile }'; done

Vì vậy, do các ràng buộc, bạn cần gọi awknhiều lần, mặc dù bạn chỉ có thể làm điều đó một lần với các tệp không nén. Và chắc chắn, sẽ tốt hơn nếu chỉ làm zawk '/pattern/ {print FILENAME; nextfile}' *và có được hiệu quả tương tự, vì vậy tôi thích các giải pháp cho phép điều này.


1
Bạn không cần chúng phải gzipthân thiện, chỉ cần zcatcác tệp trước.
terdon

@terdon Tôi đã chỉnh sửa bài đăng, giải thích lý do tại sao tôi đề cập rằng các tệp được nén.
arekolek

Không có nhiều khác biệt giữa việc khởi chạy awk một lần hoặc nhiều lần. Ý tôi là, OK, một số chi phí nhỏ nhưng tôi nghi ngờ bạn thậm chí sẽ nhận thấy sự khác biệt. Tất nhiên, có thể làm cho awk / perl bất cứ kịch bản nào tự làm điều này nhưng nó bắt đầu trở thành một chương trình toàn diện và không phải là một phần mềm nhanh chóng. Đó là điều bạn muốn?
terdon

@terdon Cá nhân, khía cạnh quan trọng hơn đối với tôi là lệnh sẽ phức tạp như thế nào (tôi đoán lần chỉnh sửa thứ hai của tôi xuất hiện trong khi bạn đang bình luận). Ví dụ: các grepgiải pháp có thể dễ dàng thích ứng chỉ bằng cách grepgọi tiền tố với a z, tôi cũng không cần phải xử lý tên tệp.
arekolek

Vâng, nhưng đó là grep. AFAIK, chỉ grepcatcó "biến thể z" tiêu chuẩn. Tôi không nghĩ bạn sẽ nhận được bất cứ điều gì đơn giản hơn là sử dụng một for f in *; do zcat -f $f ...giải pháp. Bất cứ điều gì khác sẽ phải là một chương trình đầy đủ kiểm tra các định dạng tệp trước khi mở hoặc sử dụng thư viện để làm tương tự.
terdon

Câu trả lời:


13
awk 'FNR == 1 { f1=f2=f3=0; };

     /one/   { f1++ };
     /two/   { f2++ };
     /three/ { f3++ };

     f1 && f2 && f3 {
       print FILENAME;
       nextfile;
     }' *

Nếu bạn muốn tự động xử lý các tệp được nén, hãy chạy nó trong một vòng lặp với zcat(chậm và không hiệu quả vì bạn sẽ sử dụng awknhiều lần trong một vòng lặp, một lần cho mỗi tên tệp) hoặc viết lại cùng một thuật toán perlvà sử dụng IO::Uncompress::AnyUncompressmô-đun thư viện có thể giải nén một số loại tệp nén khác nhau (gzip, zip, bzip2, lzop). hoặc trong python, cũng có các mô-đun để xử lý các tệp nén.


Đây là perlphiên bản sử dụng IO::Uncompress::AnyUncompressđể cho phép bất kỳ số lượng mẫu và bất kỳ số tên tệp nào (chứa văn bản thuần túy hoặc văn bản nén).

Tất cả các đối số trước đây --được coi là mô hình tìm kiếm. Tất cả các args sau --được coi là tên tập tin. Xử lý tùy chọn nguyên thủy nhưng hiệu quả cho công việc này. Xử lý tùy chọn tốt hơn (ví dụ để hỗ trợ -itùy chọn cho các tìm kiếm không phân biệt chữ hoa chữ thường) có thể đạt được bằng Getopt::Stdhoặc Getopt::Longcác mô-đun.

Chạy nó như vậy:

$ ./arekolek.pl one two three -- *.gz *.txt
1.txt.gz
4.txt.gz
5.txt.gz
1.txt
4.txt
5.txt

(Tôi sẽ không liệt kê các tệp {1..6}.txt.gz{1..6}.txtở đây ... chúng chỉ chứa một số hoặc tất cả các từ "một" "hai" "ba" "bốn" "năm" và "sáu" để kiểm tra. Các tệp được liệt kê ở đầu ra ở trên NÊN chứa cả ba mẫu tìm kiếm. Tự kiểm tra nó với dữ liệu của riêng bạn)

#! /usr/bin/perl

use strict;
use warnings;
use IO::Uncompress::AnyUncompress qw(anyuncompress $AnyUncompressError) ;

my %patterns=();
my @filenames=();
my $fileargs=0;

# all args before '--' are search patterns, all args after '--' are
# filenames
foreach (@ARGV) {
  if ($_ eq '--') { $fileargs++ ; next };

  if ($fileargs) {
    push @filenames, $_;
  } else {
    $patterns{$_}=1;
  };
};

my $pattern=join('|',keys %patterns);
$pattern=qr($pattern);
my $p_string=join('',sort keys %patterns);

foreach my $f (@filenames) {
  #my $lc=0;
  my %s = ();
  my $z = new IO::Uncompress::AnyUncompress($f)
    or die "IO::Uncompress::AnyUncompress failed: $AnyUncompressError\n";

  while ($_ = $z->getline) {
    #last if ($lc++ > 100);
    my @matches=( m/($pattern)/og);
    next unless (@matches);

    map { $s{$_}=1 } @matches;
    my $m_string=join('',sort keys %s);

    if ($m_string eq $p_string) {
      print "$f\n" ;
      last;
    }
  }
}

Hàm băm %patternschứa tập hợp đầy đủ các mẫu mà các tệp phải chứa ít nhất một trong số mỗi thành viên $_pstringlà một chuỗi chứa các khóa được sắp xếp của hàm băm đó. Chuỗi $patternchứa một biểu thức chính quy được biên dịch trước cũng được xây dựng từ %patternshàm băm.

$patternđược so sánh với từng dòng của mỗi tệp đầu vào (sử dụng công cụ /osửa đổi để biên dịch $patternchỉ một lần vì chúng tôi biết nó sẽ không bao giờ thay đổi trong quá trình chạy) và map()được sử dụng để tạo hàm băm (% s) có chứa các kết quả khớp cho mỗi tệp.

Bất cứ khi nào tất cả các mẫu đã được nhìn thấy trong tệp hiện tại (bằng cách so sánh nếu $m_string(các phím được sắp xếp trong %s) bằng $p_string), hãy in tên tệp và chuyển sang tệp tiếp theo.

Đây không phải là một giải pháp đặc biệt nhanh, nhưng không chậm một cách vô lý. Phiên bản đầu tiên mất 4m58 để tìm kiếm ba từ trong tệp nhật ký nén trị giá 74 MB (tổng cộng 937 MB không nén). Phiên bản hiện tại này mất 1m13s. Có lẽ có những tối ưu hơn nữa có thể được thực hiện.

Một tối ưu hóa rõ ràng là sử dụng này kết hợp với xargs's -Paka --max-procsđể chạy nhiều tìm kiếm trên các tập con của các tập tin trong song song. Để làm điều đó, bạn cần đếm số lượng tệp và chia cho số lõi / cpus / luồng mà hệ thống của bạn có (và làm tròn bằng cách thêm 1). ví dụ: có 269 tệp đang được tìm kiếm trong bộ mẫu của tôi và hệ thống của tôi có 6 lõi (AMD 1090T), vì vậy:

patterns=(one two three)
searchpath='/var/log/apache2/'
cores=6
filecount=$(find "$searchpath" -type f -name 'access.*' | wc -l)
filespercore=$((filecount / cores + 1))

find "$searchpath" -type f -print0 | 
  xargs -0r -n "$filespercore" -P "$cores" ./arekolek.pl "${patterns[@]}" --

Với tối ưu hóa đó, chỉ mất 23 giây để tìm thấy tất cả 18 tệp phù hợp. Tất nhiên, điều tương tự có thể được thực hiện với bất kỳ giải pháp nào khác. LƯU Ý: Thứ tự tên tệp được liệt kê trong đầu ra sẽ khác nhau, do đó có thể cần được sắp xếp sau đó nếu vấn đề đó xảy ra.

Như @arekolek đã lưu ý, nhiều zgreps có find -exechoặc xargscó thể thực hiện nhanh hơn đáng kể, nhưng tập lệnh này có lợi thế là hỗ trợ bất kỳ số mẫu nào để tìm kiếm và có khả năng xử lý một số loại nén khác nhau.

Nếu tập lệnh bị giới hạn chỉ kiểm tra 100 dòng đầu tiên của mỗi tệp, thì tập lệnh sẽ chạy qua tất cả chúng (trong mẫu 74 MB của tôi là 269 tệp) trong 0,6 giây. Nếu điều này hữu ích trong một số trường hợp, nó có thể được tạo thành một tùy chọn dòng lệnh (ví dụ -l 100) nhưng nó có nguy cơ không tìm thấy tất cả các tệp phù hợp.


BTW, theo trang man cho IO::Uncompress::AnyUncompress, các định dạng nén được hỗ trợ là:


Một tối ưu hóa cuối cùng (tôi hy vọng). Bằng cách sử dụng PerlIO::gzipmô-đun (được đóng gói trong debian như libperlio-gzip-perl) thay vì IO::Uncompress::AnyUncompresstôi giảm thời gian xuống còn khoảng 3,1 giây để xử lý 74 MB tệp nhật ký của mình. Ngoài ra còn có một số cải tiến nhỏ bằng cách sử dụng hàm băm đơn giản thay vì Set::Scalar(cũng lưu một vài giây với IO::Uncompress::AnyUncompressphiên bản).

PerlIO::gzipđã được đề xuất là gunzip perl nhanh nhất trong /programming//a/1539271/137158 (được tìm thấy với một tìm kiếm google cho perl fast gzip decompress)

Sử dụng xargs -Pvới điều này đã không cải thiện nó cả. Trong thực tế, nó thậm chí dường như làm chậm nó xuống bất cứ nơi nào từ 0,1 đến 0,7 giây. (Tôi đã thử bốn lần chạy và hệ thống của tôi thực hiện các công việc khác trong nền sẽ thay đổi thời gian)

Giá là phiên bản của tập lệnh này chỉ có thể xử lý các tệp được nén và không nén. Tốc độ so với tính linh hoạt: 3,1 giây cho phiên bản này so với 23 giây cho IO::Uncompress::AnyUncompressphiên bản có xargs -Ptrình bao bọc (hoặc 1m13 không có xargs -P).

#! /usr/bin/perl

use strict;
use warnings;
use PerlIO::gzip;

my %patterns=();
my @filenames=();
my $fileargs=0;

# all args before '--' are search patterns, all args after '--' are
# filenames
foreach (@ARGV) {
  if ($_ eq '--') { $fileargs++ ; next };

  if ($fileargs) {
    push @filenames, $_;
  } else {
    $patterns{$_}=1;
  };
};

my $pattern=join('|',keys %patterns);
$pattern=qr($pattern);
my $p_string=join('',sort keys %patterns);

foreach my $f (@filenames) {
  open(F, "<:gzip(autopop)", $f) or die "couldn't open $f: $!\n";
  #my $lc=0;
  my %s = ();
  while (<F>) {
    #last if ($lc++ > 100);
    my @matches=(m/($pattern)/ogi);
    next unless (@matches);

    map { $s{$_}=1 } @matches;
    my $m_string=join('',sort keys %s);

    if ($m_string eq $p_string) {
      print "$f\n" ;
      close(F);
      last;
    }
  }
}

for f in *; do zcat $f | awk -v F=$f '/one/ {a++}; /two/ {b++}; /three/ {c++}; a&&b&&c { print F; nextfile }'; donehoạt động tốt, nhưng thực sự, mất gấp 3 lần grepgiải pháp của tôi và thực sự phức tạp hơn.
arekolek

1
OTOH, đối với các tệp văn bản đơn giản, nó sẽ nhanh hơn. và cùng một thuật toán được triển khai trong một ngôn ngữ có hỗ trợ đọc các tệp nén (như perl hoặc python) như tôi đề xuất sẽ nhanh hơn nhiều greps. "phức tạp" là một phần chủ quan - cá nhân, tôi nghĩ rằng một kịch bản awk hoặc perl hoặc python duy nhất ít phức tạp hơn nhiều greps có hoặc không tìm thấy .... câu trả lời của @ terdon là tốt, và nó không cần mô-đun tôi đã đề cập (nhưng với chi phí giả mạo zcat cho mỗi tệp được nén)
cas

Tôi đã phải apt-get install libset-scalar-perlsử dụng kịch bản. Nhưng nó dường như không chấm dứt trong bất kỳ thời gian hợp lý.
arekolek

có bao nhiêu và kích thước (nén và không nén) là các tệp bạn đang tìm kiếm? Hàng chục hoặc hàng trăm tệp kích thước trung bình nhỏ hoặc hàng ngàn tệp lớn?
cas

Đây là biểu đồ kích thước của các tệp nén (20 đến 100 tệp, tối đa 50 MB nhưng chủ yếu dưới 5 MB). Không bị nén trông giống nhau, nhưng với kích thước nhân với 10.
arekolek

11

Đặt dấu tách bản ghi thành .để awksẽ coi toàn bộ tệp là một dòng:

awk -v RS='.' '/one/&&/two/&&/three/{print FILENAME}' *

Tương tự với perl:

perl -ln00e '/one/&&/two/&&/three/ && print $ARGV' *

3
Khéo léo. Lưu ý rằng điều này sẽ tải toàn bộ tệp vào bộ nhớ và đó có thể là một vấn đề đối với các tệp lớn.
terdon

Tôi ban đầu ủng hộ điều này, bởi vì nó có vẻ đầy hứa hẹn. Nhưng tôi không thể làm cho nó hoạt động với các tập tin được nén. for f in *; do zcat $f | awk -v RS='.' -v F=$f '/one/ && /two/ && /three/ { print F }'; doneđầu ra không có gì.
arekolek

@arekolek Vòng lặp đó hoạt động với tôi. Các tập tin của bạn được nén đúng cách?
jimmij

@arekolek bạn cần zcat -f "$f"nếu một số tệp không được nén.
terdon

Tôi cũng đã thử nó trên các tệp không nén và awk -v RS='.' '/bfs/&&/none/&&/rgg/{print FILENAME}' greptest/*.txtvẫn không trả lại kết quả, trong khi grep -l rgg $(grep -l none $(grep -l bfs greptest/*.txt))trả về kết quả mong đợi.
arekolek

3

Đối với các tệp nén, bạn có thể lặp qua từng tệp và giải nén trước. Sau đó, với một phiên bản sửa đổi một chút của các câu trả lời khác, bạn có thể làm:

for f in *; do 
    zcat -f "$f" | perl -ln00e '/one/&&/two/&&/three/ && exit(0); }{ exit(1)' && 
        printf '%s\n' "$f"
done

Tập lệnh Perl sẽ thoát với 0trạng thái (thành công) nếu tìm thấy cả ba chuỗi. Viết }{tắt của Perl cho END{}. Bất cứ điều gì tiếp theo nó sẽ được thực hiện sau khi tất cả đầu vào đã được xử lý. Vì vậy, tập lệnh sẽ thoát với trạng thái thoát không bằng 0 nếu không tìm thấy tất cả các chuỗi. Do đó, && printf '%s\n' "$f"sẽ chỉ in tên tệp nếu cả ba được tìm thấy.

Hoặc, để tránh tải tệp vào bộ nhớ:

for f in *; do 
    zcat -f "$f" 2>/dev/null | 
        perl -lne '$k++ if /one/; $l++ if /two/; $m++ if /three/;  
                   exit(0) if $k && $l && $m; }{ exit(1)' && 
    printf '%s\n' "$f"
done

Cuối cùng, nếu bạn thực sự muốn làm toàn bộ trong một kịch bản, bạn có thể làm:

#!/usr/bin/env perl

use strict;
use warnings;

## Get the target strings and file names. The first three
## arguments are assumed to be the strings, the rest are
## taken as target files.
my ($str1, $str2, $str3, @files) = @ARGV;

FILE:foreach my $file (@files) {
    my $fh;
    my ($k,$l,$m)=(0,0,0);
    ## only process regular files
    next unless -f $file ;
    ## Open the file in the right mode
    $file=~/.gz$/ ? open($fh,"-|", "zcat $file") : open($fh, $file);
    ## Read through each line
    while (<$fh>) {
        $k++ if /$str1/;
        $l++ if /$str2/;
        $m++ if /$str3/;
        ## If all 3 have been found
        if ($k && $l && $m){
            ## Print the file name
            print "$file\n";
            ## Move to the net file
            next FILE;
        }
    }
    close($fh);
}

Lưu tập lệnh ở trên như foo.plmột nơi nào đó trong của bạn $PATH, làm cho nó có thể thực thi được và chạy nó như thế này:

foo.pl one two three *

2

Trong tất cả các giải pháp được đề xuất cho đến nay, giải pháp ban đầu của tôi sử dụng grep là giải pháp nhanh nhất, hoàn thành trong 25 giây. Hạn chế của nó là rất tẻ nhạt khi thêm và xóa từ khóa. Vì vậy, tôi đã đưa ra một kịch bản (được đặt tên multi) mô phỏng hành vi, nhưng cho phép thay đổi cú pháp:

#!/bin/bash

# Usage: multi [z]grep PATTERNS -- FILES

command=$1

# first two arguments constitute the first command
command_head="$1 -le '$2'"
shift 2

# arguments before double-dash are keywords to be piped with xargs
while (("$#")) && [ "$1" != -- ] ; do
  command_tail+="| xargs $command -le '$1' "
  shift
done
shift

# remaining arguments are files
eval "$command_head $@ $command_tail"

Vì vậy, bây giờ, viết multi grep one two three -- *tương đương với đề xuất ban đầu của tôi và chạy cùng một lúc. Tôi cũng có thể dễ dàng sử dụng nó trên các tệp nén bằng cách sử dụng zgreplàm đối số đầu tiên thay thế.

Các giải pháp khác

Tôi cũng đã thử nghiệm một tập lệnh Python bằng hai chiến lược: tìm kiếm tất cả các từ khóa theo từng dòng và tìm kiếm trong toàn bộ từ khóa tập tin theo từ khóa. Chiến lược thứ hai nhanh hơn trong trường hợp của tôi. Nhưng nó chậm hơn so với chỉ sử dụng grep, hoàn thành trong 33 giây. Từng dòng từ khóa phù hợp hoàn thành trong 60 giây.

#!/usr/bin/python3

import gzip, sys

i = sys.argv.index('--')
patterns = sys.argv[1:i]
files = sys.argv[i+1:]

for f in files:
  with (gzip.open if f.endswith('.gz') else open)(f, 'rt') as s:
    txt = s.read()
    if all(p in txt for p in patterns):
      print(f)

Các kịch bản do terdon hoàn thành trong 54 giây. Trên thực tế, nó mất 39 giây thời gian, vì bộ xử lý của tôi là lõi kép. Điều này thật thú vị, bởi vì tập lệnh Python của tôi mất 49 giây thời gian trên tường (và greplà 29 giây).

Các kịch bản bởi cas thất bại trong việc chấm dứt trong thời gian hợp lý, ngay cả trên một số nhỏ các tập tin đã được xử lý với grepdưới 4 giây, vì vậy tôi đã phải giết nó.

Nhưng awkđề xuất ban đầu của anh ấy , mặc dù nó chậm hơn so grepvới thực tế, có lợi thế tiềm năng. Trong một số trường hợp, ít nhất là theo kinh nghiệm của tôi, có thể hy vọng rằng tất cả các từ khóa sẽ xuất hiện ở đâu đó trong phần đầu của tệp nếu chúng nằm trong tệp. Điều này mang lại cho giải pháp này một hiệu suất mạnh mẽ:

for f in *; do
  zcat $f | awk -v F=$f \
    'NR>100 {exit} /one/ {a++} /two/ {b++} /three/ {c++} a&&b&&c {print F; exit}'
done

Kết thúc trong một phần tư giây, trái ngược với 25 giây.

Tất nhiên, chúng tôi có thể không có lợi thế trong việc tìm kiếm các từ khóa được biết là xảy ra ở gần đầu tệp. Trong trường hợp như vậy, giải pháp mà không NR>100 {exit}mất 63 giây (50 giây thời gian trên tường).

Tập tin không nén

Không có sự khác biệt đáng kể về thời gian chạy giữa grepgiải pháp của tôi và awkđề xuất của cas , cả hai chỉ mất một phần giây để thực hiện.

Lưu ý rằng việc khởi tạo biến FNR == 1 { f1=f2=f3=0; }là bắt buộc trong trường hợp đó để đặt lại bộ đếm cho mỗi tệp được xử lý tiếp theo. Như vậy, giải pháp này yêu cầu chỉnh sửa lệnh ở ba vị trí nếu bạn muốn thay đổi từ khóa hoặc thêm từ khóa mới. Mặt khác, với grepbạn chỉ có thể nối thêm | xargs grep -l fourhoặc chỉnh sửa từ khóa bạn muốn.

Một nhược điểm của grepgiải pháp sử dụng thay thế lệnh, là nó sẽ bị treo nếu ở bất kỳ đâu trong chuỗi, trước bước cuối cùng, không có tệp phù hợp. Điều này không ảnh hưởng đến xargsbiến thể vì đường ống sẽ bị hủy bỏ khi greptrả về trạng thái khác không. Tôi đã cập nhật tập lệnh của mình để sử dụng xargsvì vậy tôi không phải tự xử lý việc này, làm cho tập lệnh đơn giản hơn.


Giải pháp Python của bạn có thể được hưởng lợi từ việc đẩy vòng lặp xuống lớp C vớinot all(p in text for p in patterns)
iruvar

@iruvar Cảm ơn lời đề nghị. Tôi đã thử (sans not) và nó đã hoàn thành trong 32 giây, vì vậy không có nhiều cải thiện, nhưng chắc chắn nó dễ đọc hơn.
arekolek

bạn có thể sử dụng một mảng kết hợp thay vì F1, f2, f3 trong awk, với key = search-mẫu, val = Count
cas

@arekolek xem phiên bản mới nhất của tôi bằng cách sử dụng PerlIO::gzipchứ không phải IO::Uncompress::AnyUncompress. bây giờ chỉ mất 3,1 giây thay vì 1m13 để xử lý 74 MB tệp nhật ký của tôi.
cas

BTW, nếu bạn đã chạy trước đó eval $(lesspipe)(ví dụ như trong .profile, v.v.), bạn có thể sử dụng lessthay vì zcat -ffortrình bao bọc vòng lặp của bạn awksẽ có thể xử lý bất kỳ loại tệp nào lesscó thể (gzip, bzip2, xz, v.v.) .... ít có thể phát hiện nếu thiết bị xuất chuẩn là một đường ống và sẽ chỉ xuất ra một luồng thành thiết bị xuất chuẩn nếu có.
cas

0

Một tùy chọn khác - cung cấp từng từ một để xargsnó chạy grepvới tệp. xargsbản thân nó có thể được thực hiện để thoát ngay khi một lệnh gọi greptrả về thất bại bằng cách quay lại 255nó (kiểm tra xargstài liệu). Tất nhiên, việc sinh ra vỏ và rèn liên quan đến giải pháp này có thể sẽ làm nó chậm lại đáng kể

printf '%s\n' one two three | xargs -n 1 sh -c 'grep -q $2 $1 || exit 255' _ file

và lặp lại

for f in *; do
    if printf '%s\n' one two three | xargs -n 1 sh -c 'grep -q $2 $1 || exit 255' _ "$f"
    then
         printf '%s\n' "$f"
    fi
done

Điều này có vẻ tốt, nhưng tôi không chắc làm thế nào để sử dụng này. Là gì _file? Tìm kiếm này trong nhiều tệp được chuyển qua làm đối số và trả về các tệp có chứa tất cả các từ khóa?
arekolek

@arekolek, đã thêm một phiên bản vòng lặp. Và như đối với _, nó được chuyển thành $0vỏ sinh sản - cái này sẽ hiển thị dưới dạng tên lệnh trong đầu ra của ps- tôi sẽ trì hoãn với chủ ở đây
iruvar
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.