Что является более кратким способом поиска текста в наборе файлов? - PullRequest
2 голосов
/ 21 октября 2008

В настоящее время я использую следующую команду, но набрать ее немного громоздко. Какая альтернатива короче?

find . -name '*.txt' -exec grep 'sometext' '{}' \; -print

Вот мои требования:

  • ограничение на расширение файла (я использую SVN и не хочу искать во всех этих каталогах .svn)
  • может по умолчанию использовать текущий каталог, но приятно иметь возможность указать другой каталог
  • должен быть рекурсивным

ОБНОВЛЕНИЕ: Вот мое лучшее решение на данный момент:

grep -r 'sometext' * --include='*.txt'

ОБНОВЛЕНИЕ № 2: После небольшого использования grep я понял, что мне больше нравится вывод моего первого метода. Итак, я последовал советам нескольких респондентов и просто создал сценарий оболочки, а теперь вызываю его с двумя параметрами (расширение и текст для поиска).

Ответы [ 9 ]

9 голосов
/ 21 октября 2008

grep имеет -r (рекурсивный) и --include (для поиска только в файлах и каталогах, соответствующих шаблону).

3 голосов
/ 22 октября 2008

Я предположение второго эфемента о подтверждении. Я пишу этот пост, чтобы выделить конкретную проблему.

В ответ на jgormley (в комментариях): ack доступен в виде одного файла, который будет работать везде, где установлена ​​правильная версия Perl (которая есть везде).

Учитывая, что на платформах, отличных от Linux, grep регулярно не принимает -R, возможно, использование ack является более переносимым.

3 голосов
/ 22 октября 2008

Установите ack и используйте

ack -aG'\.txt$' 'sometext'
3 голосов
/ 21 октября 2008

Это намного эффективнее, поскольку вызывает grep гораздо меньше раз, хотя трудно сказать, что оно более лаконично:

find . -name '*.txt' -print0 | xargs -0 grep 'sometext' /dev/null

Примечания:

/ find -print0 и xargs -0 обеспечивают правильную работу имен путей со встроенными пробелами.

Аргумент /dev/null гарантирует, что grep всегда добавляет имя файла.

3 голосов
/ 21 октября 2008

Если это слишком неудобно, напишите скрипт, который это делает, и поместите его в личный каталог bin. У меня есть сценарий 'fif', который ищет исходные файлы для текста, в основном просто делает одну находку, как у вас здесь:

#!/bin/bash

set -f  # disable pathname expansion

pattern="-iname *.[chsyl] -o -iname *.[ch]pp -o -iname *.hh -o -iname *.cc
-o -iname *.java -o -iname *.inl"
prune=""
moreargs=true
while $moreargs && [ $# -gt 0 ]; do
    case $1 in
    -h)
        pattern="-iname *.h -o -iname *.hpp -o -iname *.hh"
        shift
        ;;
    -prune)
        prune="-name $2 -prune -false -o $prune"
        shift
        shift
        ;;
    *)
        moreargs=false;
        ;;
    esac
done

find . $prune $pattern | sed 's/ /\\ /g' | xargs grep "$@"

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

2 голосов
/ 21 октября 2008

Я использую zsh, у которого есть рекурсивное сглаживание. Если вам нужно посмотреть на конкретные типы файлов, следующий пример будет эквивалентен вашему примеру:

grep 'sometext' **/*.txt

Если вам не важен тип файла, опция -r будет лучше:

grep -r 'sometext' *

Хотя, незначительная настройка вашего исходного примера даст вам именно то, что вы хотите:

find . -name '*.txt' \! -wholename '*/.svn/*' -exec grep 'sometext' '{}' \; -print

Если вы часто этим занимаетесь, сделайте это функцией (включите это в конфигурацию вашей оболочки):

function grep_no_svn {
    find . -name "${2:-*}" \! -wholename '*/.svn/*' -exec grep "$1" '{}' \; -print
}

Где первый аргумент функции - это текст, который вы ищете. Итак:

$ grep_here_no_svn "sometext"

Или:

$ grep_here_no_svn "sometext" "*.txt"
1 голос
/ 21 октября 2008

Вы можете написать скрипт (в bash или как угодно - у меня он есть в Groovy) и поместить его в путь. Э.Г.

$ myFind.sh txt targetString

где myFind.sh:

find . -name "*.$1" -exec grep $2 {} \; -print
0 голосов
/ 27 октября 2008

Вы говорите, что вам больше нравится вывод вашего метода (используя find). Единственное различие, которое я вижу между ними, заключается в том, что при выделении нескольких файлов имя файла будет отображаться впереди.

Вы всегда можете (в GNU grep, но вы должны использовать это, или -r и --include не будут работать) отключить имя файла с помощью -h (--no-filename). Напротив, для тех, кто хочет получить имена файлов, но должен использовать find по какой-то другой причине, это -H (--with-filename).

0 голосов
/ 21 октября 2008

Обычно я избегаю "найти человека", используя grep $(find . -name "*,txt")

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...