Направить find в grep -v

Направить find в grep -v

Я пытаюсь найти все файлы определенного типа, которые не содержат определенную строку. Я пытаюсь сделать это, передав find в grep -v

пример:

find -type f -name '*.java' | xargs grep -v "something something"

Кажется, это не работает. Похоже, что это просто возвращает все файлы, которые нашла команда find. Я пытаюсь найти все файлы .java, которые соответствуют определенному имени файла (например, заканчиваются на 'Pb', как в SessionPb.java) и не содержат 'extends SomethingSomething" внутри.

Подозреваю, что делаю это неправильно. Так как же должна выглядеть команда?

решение1

Здесь это не нужно xargs. Также нужно использовать опцию grepwith -L(файлы без совпадений), иначе будет выведено содержимое файла вместо его имени, как в вашем примере.

find . -type f -iname "*.java" -exec grep -L "something somethin" {} \+

решение2

Вы почти угадали...

find . -type f -iname "*.java" -print0 | xargs -0 grep -v "something something"

Точка «.» говорит о том, что начинать следует отсюда. (Ваш подразумевает это, но никогда не предполагайте).

-имяиспользует поиск без учета регистра, на всякий случай (или просто в случае отсутствия учета регистра).
-печать0отправляет имена файлов в xargs с конечным символом \x00, что предотвращает проблемы с именами файлов, содержащими пробелы.

'-0' в xargs говорит, что следует ожидать имена файлов, заканчивающиеся на \x00, а не возвращать значение.

и ваша команда grep...

В целом, понял.


РЕДАКТИРОВАТЬ::

Из вашего обновления:

find . -type f -iname "*pb.java" -print0 | xargs -0 grep -iL "something"

Должно помочь. (Добавил -L из ответа @rush, хорошая работа)

Я понимаю, что вашей команде grep нужна либо опция '-i', либо менее явная команда.

Попробуйте выполнить команду по частям... выводит ли ЭТА команда правильные имена файлов?

find . -type f -iname "*pb.java"

Если это так, то проблема, скорее всего, в том, что ваш шаблон поиска grep не соответствует (ошибка в написании? Такое случается!), либо совпадений просто нет.

Абсолютно худший случай:

grep -riL "something" *

проделает ГОРАЗДО больше работы по поиску всего, но должен дать вам какой-то результат.

решение3

Компьютер ведет себя как компьютер: он делает то, что вы ему сказали делать, а не то, что вы хотели бы, чтобы он делал.

grep -v "something something"печатает все строки, которые не содержат something something. Например, печатает две строки из следующих трех:

hello world
this is something something
something else

Для печати файлов, не содержащих extends SomethingSomethingничего, используйте -Lопцию:

grep -L -E 'extends[[:space:]]+SomethingSomething' FILENAME…

В некоторых версиях grep эта опция отсутствует -L(она не указанаPOSIX). Если у вас это не так, заставьте его ничего не выводить и используйте код возврата, чтобы вызывающая оболочка сделала то, что должна сделать.

grep -q -E 'extends[[:space:]]+SomethingSomething' FILENAME ||
echo "$FILENAME"

В качестве альтернативы можно использовать awk.

awk '
    FNR == 1 && NR != 1 && !found { print fn }
    FNR == 1 { fn = FILENAME; found = 0; }
    /extends[[:space:]]+SomethingSomething/ { found = 1 }
    END { if (fn != "" && !found) print fn }
'

В Linux или Cygwin (или другой системе с GNU grep) вам не нужно использовать find, так как grepон способен к рекурсии.

grep -R --include='*.java' -L -E 'extends[[:space:]]+SomethingSomething'

Если ваша оболочка ksh или bash или zsh, вы можете заставить оболочку выполнить сопоставление имен файлов. На bash set -o globstarсначала запустите (вы можете поместить это в свой ~/.bashrc).

grep -L -E 'extends[[:space:]]+SomethingSomething' **/*.java

решение4

find -type f -name '*.java' 2>&1 | grep -v "something something"

то, что вы «выводите», отображается в stderr, а не в stdout.

команда выше перенаправляет stderr в stdout

Источник

Связанный контент