Команда Unix для отображения файлов, содержащих строку, но * NOT *, содержащих другую строку
Как я рекурсивно просматриваю список файлов с одной строкой и, в частности, не имеет другой строки? Кроме того, я хочу оценить текст файлов, а не имена файлов.
Вывод:
В соответствии с комментариями я закончил использование:
find . -name "*.html" -exec grep -lR 'base\-maps' {} \; | xargs grep -L 'base\-maps\-bot'
Это возвращенные файлы с "базовыми картами", а не "base-maps-bot". Спасибо!
Ответы
Ответ 1
Попробуйте следующее:
grep -rl <string-to-match> | xargs grep -L <string-not-to-match>
Объяснение: grep -lr
делает grep рекурсивно (r) выводит список (l) всех файлов, содержащих <string-to-match>
. xargs перебирает эти файлы, вызывая grep -L
для каждого из них. grep -L
будет выводить только имя файла, если файл не содержит <string-not-to-match>
.
Ответ 2
Использование xargs в ответах выше не требуется; вы можете достичь такой же цели:
find . -type f -exec grep -q <string-to-match> {} \; -not -exec grep -q <string-not-to-match> {} \; -print
grep -q
означает, что выполняется тихо, но возвращает код выхода, указывающий, было ли найдено совпадение; find
может затем использовать этот код выхода, чтобы определить, продолжать ли выполнение остальных его опций. Если -exec grep -q <string-to-match> {} \;
возвращает 0, то он будет продолжать выполнение -not -exec grep -q <string-not-to-match>{} \;
. Если это также возвращает 0, оно будет продолжаться, чтобы выполнить -print
, который печатает имя файла.
Как заметил еще один ответ, использование find
таким образом имеет большие преимущества перед grep -Rl
, когда вы хотите искать файлы определенного типа. Если, с другой стороны, вы действительно хотите искать все файлы, grep -Rl
, вероятно, быстрее, так как он использует один grep
процесс для первого фильтра для всех файлов вместо отдельного процесса grep
для каждого файла.
Ответ 3
Эти ответы кажутся не такими, как строки BOTH. Следующая команда должна работать лучше:
grep -l <string-to-match> * | xargs grep -c <string-not-to-match> | grep '\:0'
Ответ 4
Вот более общая конструкция:
find . -name <nameFilter> -print0 | xargs -0 grep -Z -l <patternYes> | xargs -0 grep -L <patternNo>
Эта команда выводит файлы, имя которых соответствует <nameFilter>
(скорректируйте предикаты find
по мере необходимости), которые содержат <patternYes>
, но не содержат <patternNo>
.
Усовершенствования:
- Он работает с именами файлов, содержащими пробелы.
- Он позволяет фильтровать файлы по имени.
Если вам не нужно фильтровать по имени (часто нужно рассмотреть все файлы в текущем каталоге), вы можете удалить find
и добавить -R
к первому grep
:
grep -R -Z -l <patternYes> | xargs -0 grep -L <patternNo>
Ответ 5
находить. -maxdepth 1 -name "*.py" -exec grep -L "строка, которая не соответствует" {} \;
Эта команда получит все ".py" файлы, которые не содержат "string-not-to-match" в одном каталоге.