Как найти все файлы, содержащие определенный текст в Linux?

Я пытаюсь найти способ сканировать всю мою систему Linux для всех файлов, содержащих определенную строку текста. Просто чтобы уточнить, я ищу текст в файле, а не в имени файла.

Когда я искал, как это сделать, я дважды сталкивался с этим решением:

find / -type f -exec grep -H 'text-to-find-here' {} \;

Тем не менее, это не работает. Кажется, для отображения каждого файла в системе.

Это близко к правильному способу сделать это? Если нет, то как я должен? Эта возможность находить текстовые строки в файлах была бы чрезвычайно полезна для некоторых программных проектов, которыми я занимаюсь.

56 ответов

Решение

Сделайте следующее:

grep -rnw '/path/to/somewhere/' -e 'pattern'
  • -r или же -R рекурсивен,
  • -n номер строки, и
  • -w означает совпадение всего слова.
  • -l (нижний регистр L) можно добавить, чтобы просто дать имя файла совпадающих файлов.

Наряду с этим, --exclude, --include, --exclude-dir флаги могут быть использованы для эффективного поиска:

  • Это будет искать только в тех файлах, которые имеют расширения.c или.h:

    grep --include=\*.{c,h} -rnw '/path/to/somewhere/' -e "pattern"
    
  • Это исключит поиск всех файлов, заканчивающихся расширением.o:

    grep --exclude=*.o -rnw '/path/to/somewhere/' -e "pattern"
    
  • Для каталогов можно исключить определенный каталог (и) через --exclude-dir параметр. Например, это исключит dirs dir1/, dir2/ и все они будут соответствовать *.dst/:

    grep --exclude-dir={dir1,dir2,*.dst} -rnw '/path/to/somewhere/' -e "pattern"
    

Это работает очень хорошо для меня, чтобы достичь почти такой же цели, как ваша.

Для более подробной информации проверьте man grep,

Ты можешь использовать grep -ilR:

grep -Ril "text-to-find-here" /
  • i означает игнорировать регистр (необязательно в вашем случае).
  • R обозначает рекурсивный.
  • l расшифровывается как "показать имя файла, а не сам результат".
  • / обозначает начало в корне вашей машины.

Вы можете использовать ACK. Это как grep для исходного кода. Вы можете сканировать всю вашу файловую систему с ним.

Просто делать:

ack 'text-to-find-here'

В вашем корневом каталоге.

Вы также можете использовать регулярные выражения, указать тип файла и т. Д.


ОБНОВИТЬ

Я только что обнаружил Серебряный Искатель, который похож на ack, но в 3-5 раз быстрее, чем он, и даже игнорирует шаблоны из .gitignore файл.

Ты можешь использовать:

grep -r "string to be searched"  /path/to/dir

r расшифровывается как рекурсивный, поэтому будет выполнять поиск по указанному пути, а также по его подкаталогам. Это скажет вам имя файла, а также распечатает строку в файле, где появляется строка.

Или команда, аналогичная той, которую вы пытаетесь (пример:) искать во всех файлах javascript (*.js):

find . -name '*.js' -exec grep -i 'string to search for' {} \; -print

Это напечатает строки в файлах, где появляется текст, но не напечатает имя файла.

В дополнение к этой команде мы также можем написать это:grep -rn "String to search" / path / to / directory / или / file-r: рекурсивный поискn: номер строки будет показан для совпадений

Вы можете использовать это:

grep -inr "Text" folder/to/be/searched/

grep ( GNU или BSD)

Ты можешь использовать grep инструмент для рекурсивного поиска текущей папки, например:

grep -r "class foo" .

Замечания: -r - Рекурсивный поиск по подкаталогам.

Вы также можете использовать синтаксис globbing для поиска в определенных файлах, таких как:

grep "class foo" **/*.c

Примечание: с помощью опции "Globbing" ( ** ), он сканирует все файлы рекурсивно с определенным расширением или шаблоном. Чтобы включить этот синтаксис, запустите: shopt -s globstar , Вы также можете использовать **/*.* для всех файлов (кроме скрытых и без расширения) или любого другого шаблона.

Если вы ошиблись в том, что ваш аргумент слишком длинный, попробуйте сузить область поиска или используйте find синтаксис вместо, такой как:

find . -name "*.php" -execdir grep -nH --color=auto foo {} ';'

Альтернативно использовать ripgrep,

ripgrep

Если вы работаете над большими проектами или большими файлами, вы должны использовать ripgrep вместо этого, как:

rg "class foo" .

Ознакомьтесь с документами, инструкциями по установке или исходным кодом на странице проекта GitHub.

Это намного быстрее, чем любой другой инструмент, такой как GNU / BSD grep, ucg, ag, sift, ack, pt или аналогичный, поскольку он построен на основе движка регулярных выражений Rust, который использует конечные автоматы, SIMD и агрессивные буквальные оптимизации, чтобы сделать поиск очень быстрым.

Он поддерживает шаблоны игнорирования, указанные в .gitignore файлы, поэтому один путь к файлу может быть сопоставлен с несколькими шаблонами глобуса одновременно.


Вы можете использовать общие параметры, такие как:

  • -i - Нечувствительный поиск.
  • -I - игнорировать двоичные файлы.
  • -w - Поиск целых слов (в отличие от частичного совпадения слов).
  • -n - Показать линию вашего матча.
  • -C / --context (например -C5) - Увеличивает контекст, поэтому вы видите окружающий код.
  • --color=auto - Отметьте соответствующий текст.
  • -H - Отображает имя файла, где находится текст.
  • -c - Отображает количество совпадающих линий. Может сочетаться с -H,

Список имен файлов, содержащих данный текст

Прежде всего, я считаю, что вы использовали -H вместо -l, Также вы можете попробовать добавить текст в кавычки с последующим {} \,

find / -type f -exec grep -l "text-to-find-here" {} \; 

пример

Допустим, вы ищете файлы, содержащие определенный текст "Лицензия Apache" внутри вашего каталога. Он будет отображать результаты, аналогичные приведенным ниже (выходные данные будут отличаться в зависимости от содержимого каталога).

bash-4.1$ find . -type f -exec grep -l "Apache License" {} \; 
./net/java/jvnet-parent/5/jvnet-parent-5.pom
./commons-cli/commons-cli/1.3.1/commons-cli-1.3.1.pom
./io/swagger/swagger-project/1.5.10/swagger-project-1.5.10.pom
./io/netty/netty-transport/4.1.7.Final/netty-transport-4.1.7.Final.pom
./commons-codec/commons-codec/1.9/commons-codec-1.9.pom
./commons-io/commons-io/2.4/commons-io-2.4.pom
bash-4.1$ 

Удалить регистр чувствительности

Даже если вы не используете в этом случае, как "текст" против "ТЕКСТ", вы можете использовать -i переключиться, чтобы игнорировать регистр. Вы можете прочитать более подробную информацию здесь.

Надеюсь, это поможет вам.

Эта команда grep даст вам точный результат при поиске определенного текста в Linux —

grep -inRsH "Text to be searched" /path/to/dir (it can be '.')

  • iозначает игнорирование различий в регистре

  • Rозначает рекурсивный, а также включает символические ссылки. Лучше использовать 'R' вместо 'r'

  • nозначает «будет печатать номер строки».

  • sозначает "подавлять сообщения об ошибках"

  • Hозначает «он будет печатать имя файла для каждого совпадения».

Если твой grep не поддерживает рекурсивный поиск, вы можете комбинировать find с xargs:

find / -type f | xargs grep 'text-to-find-here'

Я считаю, что это легче запомнить, чем формат для find -exec,

Это выведет имя файла и содержимое совпавшей строки, например

/home/rob/file:text-to-find-here

Необязательные флаги, к которым вы можете добавить grep:

  • -i - поиск без учета регистра
  • -l - выводить только имя файла, в котором найдено совпадение
  • -h - выводить только строку, которая соответствует (не имя файла)

Есть новая утилита под названием Silversearcher

sudo apt install silversearcher-ag

Он работает в тесном сотрудничестве с Git и другими VCS. Так что вы ничего не получите в .git или другом каталоге.

Вы можете просто использовать

ag -ia "Search query"

И это сделает задачу за вас!

grep -insr "pattern" *
  • i: Игнорировать различия регистра как в PATTERN, так и во входных файлах.
  • n: Префикс каждой строки вывода с номером строки на основе 1 в своем входном файле.
  • s: Подавлять сообщения об ошибках несуществующих или нечитаемых файлов.
  • r: Рекурсивно читать все файлы в каждом каталоге.

Как найти все файлы, содержащие определенный текст в Linux? (...)

Я сталкивался с этим решением дважды:

find / -type f -exec grep -H 'text-to-find-here' {} \;


Если вы используете find как в вашем примере, лучше добавьте -s (--no-messages) чтобы grep, а также 2>/dev/null в конце команды, чтобы избежать большого количества сообщений об отказе в разрешении, выданных grep а также find:

find / -type f -exec grep -sH 'text-to-find-here' {} \; 2>/dev/null

find - это стандартный инструмент для поиска файлов - в сочетании с grep при поиске определенного текста - на Unix-подобных платформах. Кстати, команда find часто сочетается с xargs.

Для этой цели существуют более быстрые и простые инструменты - см. Ниже. Лучше их попробовать, если они доступны на вашей платформе, конечно:

Более быстрые и легкие альтернативы

RipGrep - самый быстрый инструмент поиска:

rg 'text-to-find-here' / -l

Серебряный Искатель:

ag 'text-to-find-here' / -l

подтверждение:

ack 'text-to-find-here' / -l

Примечание: вы можете добавить 2>/dev/null к этим командам, чтобы скрыть много сообщений об ошибках.


Предупреждение: если вы действительно не можете избежать этого, не ищите из '/' (корневого каталога), чтобы избежать длительного и неэффективного поиска! Поэтому в приведенных выше примерах вам лучше заменить ' / ' на имя подкаталога, например, "/home", в зависимости от того, где вы действительно хотите искать...

Использование pwd искать из любого каталога, в котором вы находитесь, возвращаясь вниз

grep -rnw `pwd` -e "pattern"

Обновление В зависимости от используемой версии grep, вы можете опустить pwd, На более новых версиях . похоже на случай по умолчанию для grep, если каталог не задан таким образом:

grep -rnw -e "pattern"

или же

grep -rnw "pattern"

будет делать то же самое, что и выше!

Пытаться:

find . -name "*.txt" | xargs grep -i "text_pattern"
grep -lrnw '/root/Desktop/ipozal' -e 'geolocation'

Если вы строго хотите использовать find затем:

1.Use find искать файлы,

2. Затем выполнить grep на всех из них.

Может быть объединен в одну команду, как показано ниже:

find /path/to/somewhere/ -type f -exec grep -nw 'textPattern' {} \;

  • использование -name Pattern если хотите grep только определенные файлы:

    find /path/to/somewhere/ -type f -name \*.cpp -exec grep -nw 'textPattern' {} \;

Это может дать вам силу find найти файлы. Вы можете играть с ним и использовать различные варианты find улучшить или сузить поиск файлов.

grep может использоваться, даже если мы не ищем строку.

Просто работает,

grep -RIl "" .

распечатает путь ко всем текстовым файлам, т. е. содержащим только печатные символы.

Silver Searcher - потрясающий инструмент, но ripgrep может быть даже лучше.

Он работает на Linux, Mac и Windows и был написан на Hacker News пару месяцев назад (здесь есть ссылка на блог Эндрю Галланта, на котором есть ссылка на GitHub):

Ripgrep - новый инструмент поиска в командной строке

Есть ack инструмент, который будет делать именно то, что вы ищете.

http://linux.die.net/man/1/ack

ack -i search_string folder_path/*

Вы можете игнорировать -i для поиска с учетом регистра

Вот несколько списков команд, которые можно использовать для поиска файла.

grep "text string to search” directory-path

grep [option] "text string to search” directory-path

grep -r "text string to search” directory-path

grep -r -H "text string to search” directory-path

egrep -R "word-1|word-2” directory-path

egrep -w -R "word-1|word-2” directory-path

Я очарован тем, как просто grep делает это с 'rl'

grep -rl 'pattern_to_find' /path/where/to/find

-r to find recursively file / directory inside directories..
-l to list files matching the 'pattern'

Используйте '-r' без 'l', чтобы увидеть имена файлов, за которыми следует текст, в котором найден шаблон!

grep -r 'pattern_to_find' /path/where/to/find

Работает просто отлично..

Надеюсь, поможет!

      grep "text-to-find-here" file_name

или же

      grep "text-to-find-here" directory_path/*

Если вы хотите выполнить поиск в текущем каталоге:

      grep "text-to-find-here" *

Если вы находитесь в репозитории git, вы можете использовать:

      git grep something

Надеюсь, это поможет...

Расширяя grep бит, чтобы дать больше информации в выводе, например, чтобы получить номер строки в файле, где находится текст, можно сделать следующим образом:

find . -type f -name "*.*" -print0 | xargs --null grep --with-filename --line-number --no-messages --color --ignore-case "searthtext"

И если у вас есть представление о типе файла, вы можете сузить область поиска, указав расширения типов файлов для поиска, в этом случае .pas ИЛИ ЖЕ .dfm файлы:

find . -type f \( -name "*.pas" -o -name "*.dfm" \) -print0 | xargs --null grep --with-filename --line-number --no-messages --color --ignore-case "searchtext"

Краткое объяснение вариантов:

  1. . в find указывает из текущего каталога.
  2. -name "*.*": для всех файлов (-name"*.pas"-o -name"*.dfm"): Только *.pas ИЛИ ЖЕ *.dfm файлы ИЛИ, указанные с помощью -o
  3. -type f указывает, что вы ищете файлы
  4. -print0 а также --null на другой стороне | (труба) являются решающими, передавая имя файла из find к grep встроен в xargs, позволяя передавать имена файлов с пробелами в именах файлов, позволяя grep обрабатывать путь и имя файла как одну строку, а не разбивать их на каждый пробел.

Просто find может работать удобно. псевдоним это в вашем ~/.bashrc файл:

alias ffind find / -type f | xargs grep

Запустите новый терминал и выполните команду:

ffind 'text-to-find-here'
find /path -type f -exec grep -l "string" {} \;

Объяснение из комментариев

find - это команда, которая позволяет вам находить файлы и другие объекты, такие как каталоги и ссылки, в подкаталогах данного пути. Если вы не указываете маску, которой должны соответствовать имена файлов, она перечисляет все объекты каталога.

-type f specifies that it should proceed only files, not directories etc.
-exec grep specifies that for every found file, it should run grep command, passing its filename as an argument to it, by replacing {} with the filename

Пытаться:

find / -type f -exec grep -H 'text-to-find-here' {} \;

который будет искать все файловые системы, потому что / это корневая папка.

Для использования домашней папки:

find ~/ -type f -exec grep -H 'text-to-find-here' {} \;

Для текущей папки используйте:

find ./ -type f -exec grep -H 'text-to-find-here' {} \;

grep твой хороший друг, чтобы достичь этого.

grep -r <text_fo_find> <directory>

если вам не важен текст, который нужно найти, используйте

grep -ir <text_to_find> <directory>

Чтобы найти строку и вывести только эту строку со строкой поиска:

for i in $(find /path/of/target/directory -type f); do grep -i "the string to look for" "$i"; done

например:

for i in $(find /usr/share/applications -type f); \
do grep -i "web browser" "$i"; done

Чтобы отобразить имя файла, содержащее строку поиска:

for i in $(find /path/of/target/directory -type f); do if grep -i "the string to look for" "$i" > /dev/null; then echo "$i"; fi; done;

например:

for i in $(find /usr/share/applications -type f); \
do if grep -i "web browser" "$i" > /dev/null; then echo "$i"; \
fi; done;

Я написал скрипт Python, который делает что-то подобное. Вот как следует использовать этот скрипт.

./sniff.py path pattern_to_search [file_pattern]

Первый аргумент, path, каталог, в котором мы будем искать рекурсивно. Второй аргумент, pattern_to_search, является регулярным выражением, которое мы хотим найти в файле. Мы используем формат регулярного выражения, определенный в Python re библиотека. В этом сценарии . также соответствует переводу строки.

Третий аргумент, file_patternне является обязательным. Это еще одно регулярное выражение, которое работает с именем файла. Будут рассматриваться только те файлы, которые соответствуют этому регулярному выражению.

Например, если я хочу искать файлы Python с расширением py содержащий Pool( с последующим словом AdaptorЯ делаю следующее,

./sniff.py . "Pool(.*?Adaptor"  .*py
./Demos/snippets/cubeMeshSigNeur.py:146 
./Demos/snippets/testSigNeur.py:259 
./python/moose/multiscale/core/mumbl.py:206 
./Demos/snippets/multiComptSigNeur.py:268 

И вуаля, он генерирует путь сопоставленных файлов и номер строки, по которой совпадение было найдено. Если найдено более одного совпадения, то каждый номер строки будет добавлен к имени файла.

Другие вопросы по тегам