Одна из моих любимых команд BASH:
find . -name '*.*' -exec grep 'SearchString' {} /dev/null \;
который ищет содержимое всех файлов в и ниже текущего каталога для указанной SearchString. Как разработчик, это пригодилось время от времени.
Однако из-за моего текущего проекта и структуры моей кодовой базы я хотел бы сделать эту команду BASH еще более сложной, не выполняя поиск файлов, которые находятся в каталоге или ниже каталога, содержащего «.svn», или любых файлов, которые конец ".html"
Страница MAN для поиска вроде как меня смутила. Я попытался использовать -prune, и это дало мне странное поведение. В попытке пропустить только HTML-страницы (для начала) я попытался:
find . -wholename './*.html' -prune -exec grep 'SearchString' {} /dev/null \;
и не получил поведение, на которое я надеялся. Я думаю, что я мог упустить смысл -прун. Не могли бы вы, ребята, помочь мне?
Спасибо
find
это не встроенная команда bash, а отдельная программаgrep -rl 'SearchString'
find
для поиска внутри файла.-name '*.*'
не находит все файлы: только те, которые имеют.
в своем имени (*.*
обычно это использование DOS-изма, тогда как в Unix вы обычно используете только*
для этого). Чтобы действительно сопоставить их все, просто удалите аргументfind . -exec ...
. Или, если вы хотите применить grep только к файлам (и пропустить каталоги), тогда сделайтеfind . -type f -exec ...
.Ответы:
Вы можете использовать функцию отрицания (!) В find, чтобы не сопоставлять файлы с конкретными именами:
Таким образом, если имя оканчивается на .html или содержит .svn в любом месте пути, оно не будет совпадать, и, следовательно, exec не будет выполнен.
источник
*.*
совпадения обеспечить соответствие только файлам, содержащим.
? Find будет соответствовать всем файлам при отсутствииname
директивы, поэтому приведенное выше будет соответствовать всем, кроме html и svn-wholename '*.svn*'
а не-name
..svn
каталоги были исключены из результатов поиска.! -name '.'
следует исключить.
из результатов поиска.У меня была одна и та же проблема в течение длительного времени, и есть несколько решений, которые могут быть применимы в разных ситуациях:
ack-grep
это своего рода «разработчикgrep
», который по умолчанию пропускает каталоги контроля версий и временные файлы. Наman
странице объясняется, как искать только определенные типы файлов и как определить свой собственный .grep
Собственные--exclude
и--exclude-dir
опции могут быть очень легко использованы для пропуска файловых глобусов и отдельных каталогов (к сожалению, нет глобализации для каталогов).find . \( -type d -name '.svn' -o -type f -name '*.html' \) -prune -o -print0 | xargs -0 grep ...
должно работать, но вышеупомянутые варианты, вероятно, меньше хлопот в долгосрочной перспективе.источник
Следующая
find
команда удаляет каталоги, имена которых содержат..svn
Хотя это не происходит в каталоге, сокращенный путь печатается ... (-name '*.svn'
причина!) ..Вы можете отфильтровать имена каталогов с помощью:
grep -d skip
который молча пропускает такие входные «имена каталогов».С GNU grep вы можете использовать
-H
вместо/dev/null
. Как небольшая побочная проблема:\+
может быть намного быстрее, чем\;
, например. за 1 миллион однострочных файлов, используя\;
потребовалось 4m20s , используя\+
потребовалось только 1.2S .Следующий метод использует
xargs
вместо-exec
и предполагает, что ни\n
в одном из имен файлов нет новых строк . Как используется здесь,xargs
почти так же, как найти\+
.xargs
может передавать имена файлов, которые содержат последовательные пробелы, изменяя входной разделитель на'\n'
с помощью-d
опции.Это исключает каталоги, имена которых содержат
.svn
и greps только файлы, которые не заканчиваются.html
.источник
\+
вариант действия -exec. Ура для небольших побочных проблем!+
это не специальный символ для оболочки, вам не нужно печатать\
перед ним.