Вот обзор различных методов, которые можно использовать для поиска файлов для определенных строк текста, с несколькими опциями, добавленными специально для работы только с текстовыми файлами, и игнорировать файлы двоичных файлов / приложений.
Следует отметить, однако, что поиск слова может стать немного сложным, потому что большинство инструментов для сопоставления строк попытаются найти слово в любой точке строки. Если мы говорим о слове в виде строки, которая может появляться в начале или конце строки или в одиночестве на линии или окружена пробелами и / или пунктуацией - вот когда нам понадобятся регулярные выражения, и особенно те, которые приходят от Perl. Здесь, например, мы можем использовать -P
в grep
, чтобы использовать регулярные выражения Perl, чтобы окружить его.
$ printf "A-well-a don't you know about the bird?\nWell, everybody knows that the bird is a word" | grep -noP '\bbird\b'
1:bird
2:bird
Простая grep
$ grep -rIH 'word'
-
-r
для рекурсивного поиска из текущего каталога
-
-I
для игнорирования двоичных файлов
-
-H
для вывода имени файла, в котором найдено совпадение
Подходит только для поиска.
find + grep
$ find -type f -exec grep -IH 'word' {} \;
-
find
выполняет рекурсивную поисковую часть
-
-I
- игнорировать двоичные файлы.
-
-H
для вывода имени файла, где найдена строка
-
хороший подход для объединения с другими командами внутри подоболочки, например:
$ find -type f -exec sh -c 'grep -IHq "word" "" && echo "Found in "' sh {} \;
Perl
#!/usr/bin/env perl
use File::Find;
use strict;
use warnings;
sub find_word{
return unless -f;
if (open(my $fh, $File::Find::name)){
while(my $line = <$fh>){
if ($line =~ /\bword\b/){
printf "%s\n", $File::Find::name;
close($fh);
return;
}
}
}
}
# this assumes we're going down from current working directory
find({ wanted => \&find_word, no_chdir => 1 },".")
бедный рекурсивный grep в рекурсивном скрипте bash
Это «bash way». Не идеально, вероятно, нет веской причины использовать это, когда у вас установлено grep
или perl
. Р>
#!/usr/bin/env bash
shopt -s globstar
#set -x
grep_line(){
# note that this is simple pattern matching
# If we wanted to search for whole words, we could use
# word|word\ |\ word|\ word\ )
# although when we consider punctuation characters as well - it gets more
# complex
case "" in
*word*) printf "%s\n" "";;
esac
}
readlines(){
# line count variable can be used to output on which line match occured
#line_count=1
while IFS= read -r line;
do
grep_line "$line" "$filename"
#line_count=$(($line_count+1))
done < ""
}
is_text_file(){
# alternatively, mimetype command could be used
# with *\ text\/* as pattern in case statement
case "$(file -b --mime-type "")" in
text\/*) return 0;;
*) return 1;;
esac
}
main(){
for filename in ./**/*
do
if [ -f "$filename" ] && is_text_file "$filename"
then
readlines "$filename"
fi
done
}
main "[email protected]"