Вопрос или проблема
Я пытаюсь “grep” контент из списка файлов в текущем каталоге, соответствующих расширениям asp
, html
и htm
.
Я также использую cygwin с:
- bash: 4.4.12(3)-release,
- findutils (
find
иxargs
): 4.6.0-1
Для этого я создал функцию bash:
function grepinpages() {
find ./ -type f -iname "*.asp" -or -iname "*.html" -or -iname "*.htm" -print0 | \
xargs -0 -n200 egrep "${@}" --
}
Так что я мог:
grepinpages -il "default\.asp"
И получить все файлы, содержащие без учета регистра “default.asp”.
Проблема в том, что я получаю совпадения только из нескольких файлов. На самом деле, если я изменю функцию на:
function grepinpages() {
find ./ -type f -iname "*.asp" -or -iname "*.html" -or -iname "*.htm" -print0 | \
xargs -0 -n200 echo egrep "${@}" --
}
Я получаю что-то вроде
egrep -il default\.asp -- file1.htm file2.htm dir1/file1.htm
Затем, если я упростю это еще больше:
find ./ -type f -iname "*.asp" -or -iname "*.html" -or -iname "*.htm"
Я получаю все файлы в списке!
Если я добавлю -print0
и передам дальше что-то
find ./ -type f -iname "*.asp" -or -iname "*.html" -or -iname "*.htm" -print0 | xargs -0 -n200 echo
Я снова получаю “неполный” список.
Оказалось, я не группировал “или” параметры find
в скобках. Таким образом, это исправило ситуацию для меня:
function grepinpages() {
find ./ -type f \( -iname "*.asp" -or -iname "*.html" -or -iname "*.htm" \) -print0 | \
xargs -0 -n200 egrep "${@}" --
}
Так как я указал -print0
, он относился только к -iname "*.htm"
, и никакое действие по умолчанию не предполагалось для других альтернатив, я думаю.
Ответ или решение
Когда вы используете команду find
в сочетании с xargs
, важно правильно группировать условия с помощью круглых скобок, особенно когда вы применяете логические операторы, такие как -or
. В вашем случае, проблема, с которой вы столкнулись при выполнении функции grepinpages
, была связана именно с этой причиной.
Проблема
Вы начали с команды:
find ./ -type f -iname "*.asp" -or -iname "*.html" -or -iname "*.htm" -print0 | \
xargs -0 -n200 egrep "${@}" --
При отсутствии круглых скобок вокруг условий, find
неправильно интерпретировал структуру команд. Когда вы вызываете -print0
, find
возвращает только те файлы, которые соответствуют последнему условию, в данном случае, -iname "*.htm"
. Таким образом, в результате вы получали не полный список всех файлов с расширениями .asp
, .html
и .htm
, а только те, что соответствовали последнему условию.
Решение
Для корректной работы команды важно правильно сгруппировать условия:
find ./ -type f \( -iname "*.asp" -or -iname "*.html" -or -iname "*.htm" \) -print0 | \
xargs -0 -n200 egrep "${@}" --
Использование скобок позволяет явно указать, что все три условия относятся к одной группе и оценка будет происходить над всей группой. Теперь find
будет правильно интерпретировать, что нужно искать файлы с любым из указанных расширений и выводить их в стандарте, который можно передать дальше через xargs
.
Причины возникновения проблемы
При использовании find
без группировки, каждая команда выводила отдельный результат, который не учитывал все условия одновременно. В результате, когда вы добавляли -print0
, система выполняла его только для последнего условия, игнорируя остальные.
Заключение
Чтобы избежать дальнейших проблем с интерпретацией команд, всегда группируйте логические операции. Это специально важно в таких случаях, как с find
. Применяя данный подход, вы значительно упростите задачу поиска и извлечения данных из множества файлов, что особенно критично в сценариях работы с большим количеством данных.
Таким образом, следуя указанному вами синтаксису, вы сможете эффективно и продуктивно находить нужные файлы, извлекая из них информацию без риска потерять данные из-за неверной интерпретации условий.