Як знайти файли, що не містять заданого рядкового рядка?


Відповіді:


818

Якщо ваш греп має варіант -L(або --files-without-match):

$ grep -L "foo" *

1
Як зазначено в іншому місці, ack допомагає уникнути .svn (підривної) файлів за замовчуванням.
ГуруМ

11
@GuruM Це можна зробити в GNU grep, експортувавши змінну GREP_OPTIONS='--exclude-dir=.svn --exclude-dir=.git': ^)
bufh

6
Або еквівалент, використовуючи ag :ag -L 'foo'
єпископ

5
Працює як магія! Підказка: -rLзамість того, -Lщоб відповідати підкаталогам
Ufos

1
@Larry - Більш чіткий спосіб уникнути проблем з глобалізацією - це використовувати "порожній" довгий варіант, подібний до цього: grep -L 'foo' -- *Стандарт - це те, що команди, які приймають довгі параметри, --вказують на те, що після цієї точки більше не існує варіантів.
Падді Ландау

45

Погляньте ack. Це робить.svn виключення для вас автоматично, дає вам регулярні вирази Perl і є простою завантаженням однієї програми Perl.

Еквівалент того, що ви шукаєте, має бути ack:

ack -L foo

23

Ви можете зробити це з грепом самостійно (без знаходження).

grep -riL "foo" .

Це пояснення параметрів, які використовуються на grep

     -L, --files-without-match
             each file processed.
     -R, -r, --recursive
             Recursively search subdirectories listed.

     -i, --ignore-case
             Perform case insensitive matching.

Якщо ви будете використовувати l(нижній регістр), ви отримаєте навпаки (файли зі збігами)

     -l, --files-with-matches
             Only the names of files containing selected lines are written

17

Наступна команда дає мені всі файли, які не містять шаблон foo:

find .  -not  -ipath '.*svn*' -exec  grep  -H -E -o -c  "foo"  {} \; | grep 0

4
Ви хочете змінити grep 0 в кінці на grep 0 $ (інакше ви отримаєте помилкові збіги у файлах, у яких ім'я файлу має символ 0).
клозо

9
@clouseau здебільшого правий ... Однак, вони grep '0$'б відповідали файлам, кратним 10 рядків! Вам потрібно grep ':0$'в кінці перевірити наявність явного ": 0" в кінці рядка. Тоді ви отримаєте лише файли з нульовими рядками.
TrinitronX

У UNIX, на якому я перебуваю, не було версій пошуку або grep з цими параметрами, тому мені довелося перейти з командою "ack", запропонованою в інших коментарях.
KC Baltz

14

Наступна команда виключає необхідність знаходження для фільтрації svnпапок за допомогою секунди grep.

grep -rL "foo" ./* | grep -v "\.svn"


6

Мені пощастило

grep -H -E -o -c "foo" */*/*.ext | grep ext:0

Мої спроби grep -vтільки що дали мені всі рядки без "foo".


4

Проблема

Мені потрібно переробити великий проект, який використовує .phtmlфайли для виписування HTML за допомогою вбудованого PHP-коду. Я хочу замість цього використовувати шаблони вуса . Я хочу знайти будь-які .phtmlgiles, які не містять рядокnew Mustache оскільки їх все одно потрібно переписати.

Рішення

find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$ | sed 's/..$//'

Пояснення

Перед трубами:

Знайдіть

find . Знайдіть файли рекурсивно, починаючи з цього каталогу

-iname '*.phtml'Ім'я файлу повинно містити .phtml(thei робить його нечутливим до регістру)

-exec 'grep -H -E -o -c 'new Mustache' {}'Виконайте grepкоманду на кожному зі збіжених контурів

Греп

-H Завжди друкуйте заголовки імен файлів із вихідними рядками.

-E Інтерпретувати візерунок як розширений регулярний вираз (тобто змушувати греп поводитись як егреп).

-o Друкується лише відповідна частина рядків.

-c На стандартний вихід записується лише кількість вибраних рядків.


Це дасть мені список усіх шляхів до файлів, що закінчуються .phtml, з відліком кількості разів, в якій new Mustacheвиникає рядок у кожному з них.

$> find . -iname '*.phtml$' -exec 'grep -H -E -o -c 'new Mustache' {}'\;

./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml:0
./app/MyApp/Customer/View/Account/studio.phtml:0
./app/MyApp/Customer/View/Account/orders.phtml:1
./app/MyApp/Customer/View/Account/banking.phtml:1
./app/MyApp/Customer/View/Account/applycomplete.phtml:1
./app/MyApp/Customer/View/Account/catalogue.phtml:1
./app/MyApp/Customer/View/Account/classadd.phtml:0
./app/MyApp/Customer/View/Account/orders-trade.phtml:0

Перша труба grep :0$фільтрує цей список, включаючи лише рядки, що закінчуються на :0:

$> find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$

./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml:0
./app/MyApp/Customer/View/Account/studio.phtml:0
./app/MyApp/Customer/View/Account/classadd.phtml:0
./app/MyApp/Customer/View/Account/orders-trade.phtml:0

Друга труба sed 's/..$//'знімає два останні символи кожного рядка, залишаючи лише файлові контури.

$> find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$ | sed 's/..$//'

./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml
./app/MyApp/Customer/View/Account/studio.phtml
./app/MyApp/Customer/View/Account/classadd.phtml
./app/MyApp/Customer/View/Account/orders-trade.phtml

3

Якщо ви використовуєте git, він здійснює пошук усіх відстежених файлів:

git grep -L "foo"

і ви можете шукати в підмножині відстежуваних файлів, якщо у вас увімкнено ** підкаталогічний глобул ( shopt -s globstarв .bashrc, див. це ):

git grep -L "foo" -- **/*.cpp

1

У мого грепу немає жодної опції -L. Я знаходжу рішення для досягнення цього.

Ідеї:

  1. скинути все ім’я файлу, що містить заслужений рядок, до txt1.txt.
  2. скинути все ім’я файлу в каталозі до txt2.txt.
  3. зробіть різницю між двома дамп-файлами за допомогою команди diff.

    grep 'foo' *.log | cut -c1-14 | uniq > txt1.txt
    grep * *.log | cut -c1-14 | uniq > txt2.txt
    diff txt1.txt txt2.txt | grep ">"
    

Я забуваю команди, але замість того, щоб скидати імена файлів, ви насправді можете робити diffміж двома вихідними потоками (я думаю, ви оточуєте команди круглими дужками, і там є кутовий дужок десь теж), якщо ваші системи підтримують це, що я думаю це питання, оскільки він не підтримуєgrep -L
Dexygen

1

find *20161109* -mtime -2|grep -vwE "(TRIGGER)"

Ви можете вказати фільтр під "find", а рядок виключення під "grep -vwE". Використовуйте mtime under find, якщо вам потрібно також фільтрувати модифікований час.


Це, здається, показує мені всі рядки без рядка, ОП запитує лише імена файлів.
Бен Фармер

1

Відкрити звіт про помилку

Як коментує @tukan, для Ag є відкритий звіт про помилку щодо -L/ / --files-without-matchesflag:

Оскільки у звіті про помилку є невеликий прогрес, на -Lвказану нижче опцію не слід покладатися , доки помилка не буде усунена. Використовуйте замість цього різні підходи. Посилаючись на коментар до звіту про помилку [наголос мій]:

Будь-які оновлення щодо цього? -Lповністю ігнорує збіги в першому рядку файлу. Здається, якщо це не буде виправлено найближчим часом, прапор слід повністю видалити, оскільки він фактично не працює, як рекламується .


Silver Searcher - Ag (призначена функція - див. Звіт про помилку)

Як потужна альтернатива grep, ви можете використовувати The Silver Searcher - Ag :

Засіб пошуку коду, схожий на ack, з акцентом на швидкість.

Дивлячись man ag, ми знаходимо -Lабо --files-without-matchesваріант:

...

OPTIONS
    ...

    -L --files-without-matches
           Only print the names of files that don´t contain matches.

Тобто, для рекурсивного пошуку файлів, які не відповідають foo, із поточного каталогу:

ag -L foo

Щоб шукати лише в поточному каталозі файли, які не відповідають foo, просто вкажіть --depth=0для рекурсії:

ag -L foo --depth 0

Час від часу відбувається через -Lпомилку - github.com/ggreer/the_silver_searcher/isissue/238
tukan

@tukan дякую за підказку. Я оновив відповідь; вирішивши не видаляти відповідь, а натомість відкрити інформацію про помилку.
dfri

1

Ще одна альтернатива, коли grep не має опції -L (наприклад, IBM AIX), крім нічого, крім grep та оболонки:

for file in * ; do grep -q 'my_pattern' $file || echo $file ; done

-4
grep -irnw "filepath" -ve "pattern"

або

grep -ve "pattern" < file

команда вище дасть нам результат, оскільки -v знаходить зворотну сторону шуканого шаблону


1
Це друкує рядки, які не містять візерунок. Ви можете додати -lможливість друкувати лише ім'я файлу; але це все ще друкує імена будь-якого файлу, який містить будь-який рядок, який не містить шаблон. Я вважаю, що ОП хоче знайти файли, які не містять жодної рядки, яка містить шаблон.
трійка

Команда, яку ви надали, перелічує файли у "filepath" з усіма їх рядками, які не містять "шаблону".
апродан

-6

Наступна команда може допомогти вам відфільтрувати рядки, що містять підрядку "foo".

cat file | grep -v "foo"

2
Це друкує рядки, які не збігаються, а не назви файлів, які не містять відповідності в жодному рядку. Щоб додати образи до травми, це як марне використанняcat .
трійка
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.