Я пытаюсь найти все файлы определенного типа, которые не содержат определенную строку. Я пытаюсь сделать это, передав find в grep -v
пример:
find -type f -name '*.java' | xargs grep -v "something something"
Кажется, это не работает. Похоже, что это просто возвращает все файлы, которые нашла команда find. Я пытаюсь найти все файлы .java, которые соответствуют определенному имени файла (например, заканчиваются на 'Pb', как в SessionPb.java) и не содержат 'extends SomethingSomething" внутри.
Подозреваю, что делаю это неправильно. Так как же должна выглядеть команда?
решение1
Здесь это не нужно xargs
. Также нужно использовать опцию grep
with -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