Как я могу найти все файлы, которые НЕ содержат текстовую строку?

40

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

Я попытался это (используя -v для инвертирования параметров grep) без удачи:

find . -exec grep -v -l shared.php {} \;

Кто-то сказал, что это будет работать:

find . ! -exec grep -l shared.php {} \;

Но это не похоже на работу для меня.

На этой странице есть этот пример:

find ./logs -size +1c  > t._tmp
while read filename
do
     grep -q "Process Complete" $filename
     if [ $? -ne 0 ] ; then
             echo $filename
     fi
done < t._tmp
rm -f t_tmp

Но это громоздко и совсем не кратко.

PS: я знаю, что это grep -L *будет делать, но как я могу использовать команду find в сочетании с grep для исключенных файлов, это то, что я действительно хочу знать.

pss: Также я не уверен, как заставить grep включать подкаталоги с grep -L *синтаксисом, но я все еще хочу знать, как использовать его с find:)

УХО
источник
1
Первая команда, которую вы написали, отлично работала на моем компьютере. Какую версию find вы используете? И так как мы находимся, возможно, укажите, какой Unix вы используете ..
Rahmu
@rahmu, эта команда почти всегда не работает, как вы ожидаете. Вы, вероятно, имели очень конкретный случай. Пожалуйста, смотрите unix.stackexchange.com/questions/339619/…
sgnsajgon

Ответы:

8
find . -type f | xargs grep -H -c 'shared.php' | grep 0$ | cut -d':' -f1    

ИЛИ

find . -type f -exec grep -H -c 'shared.php' {} \; | grep 0$ | cut -d':' -f1

Здесь мы вычисляем количество совпадающих строк (используя -c) в файле, если число равно 0, то это требуемый файл, поэтому мы вырезаем первый столбец, т.е. имя файла, из выходных данных.

Сачин Дивекар
источник
6
Это ужасно сложно. Смотрите ответ Кевина .
Жиль "ТАК - перестань быть злым"
@ Жиль, да, я согласен с тобой. У меня +1 его ответ.
Сачин Дивекарь
6
Это не только «ужасно сложно», но и неправильно, поскольку в нем также перечислены все файлы, которые содержат кратные 10 строк, соответствующих шаблону. Даже если это grepбыло зафиксировано в этом не будет по- прежнему считать , никаких имен файлов , содержащих :или новой строки символов ...
don_crissti
@don_crissti, спасибо за упоминание! Тем не менее, если вы не используете много кода для копирования и вставки, решение выше является довольно хорошим трюком.
Ufos
@ Ufos - я действительно не получаю ваш комментарий ... Это неправильно . В любом случае, не стесняйтесь использовать его, если он выглядит как «действительно хороший трюк» для вас ...
don_crissti
58

Ваш поиск должен сработать, если вы измените -v -l(файлы, строки которых не совпадают) на -L(файлы без соответствия строк), но вы также можете использовать опцию grep'recursive ( -r):

grep -rL shared.php .
Kevin
источник
какая находка должна работать?
cwd
@Kevin - извините, find . -exec grep -v -l shared.php {} \;(и все другие варианты, которые я пробовал) не работает для меня. Я на OS X, но я не думаю, что это должно иметь значение. Я дал тебе +1, потому что я забыл об этой -rопции.
cwd
@cwd Я знаю, что это старое, но я хочу оставить это здесь для будущих читателей: тот факт, что вы работаете в OS X, имеет значение. Mac OSX использует команды FreeBSD. Большинство людей здесь принимают команды в стиле Linux (GNU). У них разные аргументы, разные способы обработки деталей.
Rich Homolka
По состоянию на 2016 OSX, кажется, поддерживает-L
Дэвид
@ Кевин Я сказал, что это так, а не то, что это не так. :) не то, чтобы кто-то прямо сказал, что это не так, но комментарии сбивают с толку (и я, конечно, столкнулся с другими проблемами OS X / BSD и GNU).
Дэвид
4

Я знаю, что это grep -L *будет делать, но как я могу использовать findкоманду в сочетании с grepдля исключения файлов, это то, что я действительно хочу знать

Вы можете использовать findи grepнравится это:

find . -type f ! -exec grep -q 'PATTERN' {} \; -print

Здесь -printвыполняется только если предыдущее выражение: ! -exec ... {}оценивается как true.
Таким образом, для каждого найденного файла grep -q 'PATTERN'используется exec, если результатом является falseто, что все выражение ! -exec grep -q 'PATTERN'оценивается как trueи имя файла printed.

don_crissti
источник
2
У этого есть преимущество того, чтобы быть стандартным и портативным.
Стефан Шазелас
Есть разница с GNU, grep -Lхотя в том, что он также будет включать в список нечитаемые файлы.
Стефан Шазелас
1

Вы найдете не соответствующий результат по опции -L

grep -iL shared.php .
Пракаш
источник