Найти файлы, которые содержат строку и не содержат другой [дубликат]

В основном требуется информация

  • Можете ли вы отправить предыдущий вывод своих настроек и какие настройки теперь конфигурируют? Какие ошибки появляются?

  • Версии lvm актуальны и стабильны?

  • По крайней мере, у вас есть два жестких диска sda и sdc

  • Может быть, у вас есть зеркальные тома?

  • В Kubuntu включен LVM? С поддержкой зеркала?

  • Были ли у вас предыдущие резервные копии / etc / lvm? Этот каталог содержит текущую конфигурацию и более ранние версии.

1
16.01.2017, 18:20
4 ответа

Объедините find с bash -c вместо скрипта. Мы берем путь к файлу и сохраняем его в переменной file , а затем передаем его другим командам. Сначала grep -q проверит, присутствует ли одно слово / шаблон, который вы хотите. Используя свой статус выхода, && передаст его второму grep -q . Если эта команда не находит совпадения, это означает, что строка не найдена, поэтому, используя ее статус выхода, мы передаем ее в echo через оператор || .

В приведенном ниже примере только file2.txt содержит abra , но не cadabra слово.

$ find -type f -exec bash -c 'file="$@";grep -q "abra" "$file"  &&  grep -q "cadabra" "$file" || echo "$file" ' sh "{}" >
./file2.txt
$ ls                                                                                                                     
file1.txt  file2.txt  file 3.txt
$ cat file1.txt
abra cadabra
$ cat file2.txt                                                                                                          
abra
$ cat file\ 3.txt                                                                                                        
abra cadabra
0
27.01.2020, 23:34

Если я правильно прочитал требование, вы хотите, чтобы все файлы соответствовали $ PAT_INCL минус файлы, соответствующие $ PAT_EXCL .

Концептуально это просто вычитание множества. В unix нет очень хорошей стандартной утилиты для операций с множествами, но comm работает.

comm -23 <(grep --files-with-match "$PAT_INCL"  * | sort) \
         <(grep --files-with-match "$PATH_EXCL" * | sort)

Это можно сделать немного более эффективным, просто перебирая совпадающие файлы во втором grep:

# Assuming filenames without whitespace
grep --files-with-match "$PAT_INCL" * | sort > incl_files
grep --files-with-match "$PAT_EXCL" $(cat incl_files) | sort > excl_files
comm -23 incl_files excl_files
0
27.01.2020, 23:34

grep -vl сообщит имена файлов, в которых есть хотя бы одна строка, соответствующая шаблону. Здесь вам нужны файлы, в которых ни одна строка не соответствует шаблону. GNU grep (как обнаружено в Debian) имеет для этого параметр -L :

grep -rlZ printf . | xargs -r0 grep -FL '#include <stdio.h>'

С любым POSIX grep вы можете просто отрицать grep -q :

find . -type f -exec grep -q printf {} \; \
               ! -exec grep -Fq '#include <stdio.h>' {} \; \
               -print

Намного менее эффективно, поскольку это означает запуск двух экземпляров grep для каждого файла.

2
27.01.2020, 23:34

Это довольно просто:

for fname in ./*.c; do
  if grep -q -F "printf" "$fname" && ! grep -q -F "#include <stdio.h>" "$fname"; then
     printf 'File "%s" needs to include stdio.h\n' "$fname"
  fi
done

Программа просмотрит все исходные файлы C в текущем каталоге и сообщит о любом файле, который использует printf() без включения stdio.h заголовка.

Однако заголовок может быть включен косвенно, поэтому, чтобы избежать ложных срабатываний, вы можете пропустить код через препроцессор C и искать заголовок в препроцессированном выводе (похоже, это работает с gcc и clang):

for fname in ./*.c; do
  if grep -q -F "printf" "$fname" && cc -E "$fname" | ! grep -q "^#.*stdio\.h\""; then
     printf 'File "%s" needs to include stdio.h\n' "$fname"
  fi
done
0
27.01.2020, 23:34

Теги

Похожие вопросы