У меня есть приблизительно 50 000 файлов (.txt) и больше объектов в filesdir папке. Значения: 'факс', 'телефон', 'адрес' представлен в различных конфигурациях в этих файлах. Я должен найти все файлы, которые содержат 'факс' И 'звонят', и не содержит 'адрес'. Я попробовал за цикл с несколькими командами grep. ls дает 'слишком много аргументов'. Таким образом, я попробовал:
find /filesdir/ -maxdepth 1 -name '*.txt' -exec grep -l 'fax' \; grep -l 'phone' \; grep -l -v 'address'
Почему это не работает?
Существует несколько причин, которые не работали бы:
{}
заполнитель для -exec
-exec
несколько grep
команды с единственным вызовомAND
тогда как Вы, по-видимому, хотите fax
ИЛИ phone
И not address
Я не полностью протестировал его, но я думаю, что Вы хотите что-то больше как
find /filesdir/ -maxdepth 1 -name '*.txt' -exec grep -q 'fax\|phone' {} \; -exec grep -lv 'address' {} \;
Я думаю, что эта командная строка сделает это:
find -maxdepth 1 -name "*.txt" -exec echo "{} :" \; -exec cat {} \; -exec echo EOF \;| tr '\n' ' '|sed 's/EOF /\n/g'|grep -iv 'address'|grep -i 'fax'|grep -i 'phone'
Объяснение:
для каждого файла (который найден find
)
для целого вывода
Теперь содержание каждого файла находится в одной отдельной строке, подходящей для grep
.
и наконец
Предыдущая командная строка печатает имена файлов и содержание файла (объединенный с одной строкой), который хорош для тестирования, но не для обработки тысяч файлов.
Следующая командная строка печатает только имена файлов. Это использует ':::' для разделения каждого имени файла от содержания файла.
find -maxdepth 1 -name "*.txt" -exec echo "{} :::" \; -exec cat {} \; -exec echo EOF \;| tr '\n' ' '|sed 's/EOF /\n/g'|grep -iv 'address'|grep -i 'fax'|grep -i 'phone' | sed 's/ :::.*//'
git grep
Можно использовать git grep
для нескольких шаблонов, объединенных с помощью булевых выражений, например:
git grep --all-match --no-index -e "fax" --and -e "phone" --and --not -e "address"
Можно объединить различные шаблоны с булевыми выражениями такой как --and
, --or
и --not
.
--all-match
При предоставлении нескольких выражений шаблона этот флаг указан для ограничения соответствия файлами, которые имеют строки для соответствия всем им.
--no-index
Поисковые файлы в текущем каталоге, которым не управляет Мерзавец.
-l
/--files-with-matches
/--name-only
Покажите только названия файлов.
-e
Следующий параметр является шаблоном. Значение по умолчанию должно использовать основной regexp.
Другие параметрические усилители для рассмотрения:
--threads
Количество grep рабочих потоков для использования.
-q
/--quiet
/--silent
Не производите подобранные строки; выход с состоянием 0, когда существует соответствие.
Для изменения типа шаблона можно также использовать -G
/--basic-regexp
(значение по умолчанию), -F
/--fixed-strings
, -E
/--extended-regexp
, -P
/--perl-regexp
, -f file
, и другой.
Проверить man git-grep
для дальнейшей справки.
grep
Вот grep
синтаксис, который использует замены цепи инстанций:
grep -L "address" $(grep -l "phone" $(grep -rl "fax" .))
Объяснение:
grep -rl "fax" .
).grep -l "phone" $(cmd)
).address
(grep -L "address" $(cmd)
).Если Вы работаете с большими данными, рассматриваете использование ripgrep
вместо этого.
find
Выше примера может не работать хорошо с файлами с пробелами, таким образом, вот версия с find
:
find . -type f -name '*.txt' \
-execdir bash -c 'grep -L "address" "$(grep -l "phone" "$(grep -l "fax" "{}")")"' ';' \
2>/dev/null
См. также: Проверьте, существуют ли все несколько строк или regexes в файле
Для нахождения файлов (совместимыми с файлами включая пробельную/или новую строку), они не содержат шаблон address
:
find -type f ! -exec grep -q 'address' {} \; -print
и распечатайте только тех, который содержит шаблоны fax
и phone
в любом порядке в целом файле:
find -type f ! -exec grep -q 'address' {} \; \
-exec grep -qP '(?s)(?=.*?fax)(?=.*?phone)' {} \; -print
Или POSIXly:
find -type f ! -exec grep -q 'address' {} \; \
-exec grep -q 'fax' {} \; \
-exec grep -q 'phone' {} \; -print
Или принятие там нет \n
ewline на имя файлов, затем:
grep -lP '(?s)(?=.*?fax)(?=.*?phone)' * |xargs -d'\n' grep -L address
(?=pattern)
: Положительное Предвидение: положительная предварительная конструкция является парой круглых скобок, с вводной круглой скобкой, сопровождаемой вопросительным знаком и, равняется знаку.
(?s)
Известная "точка - все", который говорит grep позволять точку .
соответствовать \n
символы ewline также.
.*?
средства, соответствующие любым символам .
то, что нуль случаев или больше раз *
в то время как они дополнительные сопровождаемый шаблоном (fax
или phone
). ?
делает все дополнительным перед ним (нуль средств или одно время всего подобранного .*
)