Больше awk -ness
awk '/LEC05/{ name[$2]++ } END { n = asorti( name,sname ); for ( i in sname ) print sname[i]}' input.txt
vim $(find path/ -exec grep -l 'pattern' {} +)
— это подстановка команды без кавычек, поэтому в ее результате будет выполняться разделение слов по пробелам, а также расширение имени пути. То есть, если файл a b
совпадает, Vim неправильно откроет a
и b
. Если файл *
соответствует, увы, который будет расширен на каждый файл в соответствующем каталоге. Подходящим решением является
find path/ -type f -exec grep -q 'pattern' {} \; -exec vim {} +
Grep работает в q
режиме uiet. :Для каждого файла используется только его возвращаемое значение. Если 0
, в этом файле найдено совпадение, и файл передается в Vim.
{} \;
означает, что Grep будет анализировать один файл за раз. Если бы мы использовали {} +
, все файлы были бы переданы в качестве аргументов Grep, а найденное совпадение в любого из этих файлов привело бы к статусу выхода 0
, поэтому все эти файлы были бы открыты в Vim.. С другой стороны, {} +
используется для Vim, так что каждый найденный файл попадает в один буфер в одном процессе Vim. Вы можете попробовать изменить их, чтобы почувствовать разницу.
Если вам нужно ускорить процесс:
Если 'pattern'
не является регулярным выражением, а является фиксированным шаблоном, добавьте флаг -F
в Grep.
grep -lZ
,Xargs и специальные конструкции оболочки также должны -ускорить процесс, если они у вас есть, см. ответ Stéphane Chazelas .
И здесь другие похожие варианты использования с Xargs, Find и Vim.
С инструментами GNU (ваш --color=always
уже является расширением GNU )и оболочкой с поддержкой замены процессов в стиле Ksh -:
xargs -r0a <(grep -rlZ pattern.) vim
Или:
xargs -r0a <(find.... -exec grep -lZ pattern {} +) vim
Сzsh
:
vim ${(0)"$(find.... -exec grep -lZ pattern {} +)"}
С bash
4.4+:
readarray -td '' files < <(find.... -exec grep -lZ pattern {} +)
vim "${files[@]}"
Они минимизируют количество grep
выполняемых вызовов. Суть в том, чтобы указать grep
выводить имена файлов с разделителями NUL -, чтобы их можно было надежно разделить на отдельные аргументы для vim
с помощью GNU xargs -0
или флага расширения параметра zsh
's 0
или bash
- readarray -td ''
.
В zsh
вы также можете:
vim./**/*(...e['grep -q pattern $REPLY'])
(где ...
заменяет дополнительные квалификаторы, которые вы можете добавить, например, find
подход ).
Однако это означает, что, как и в подходах, использующих find -exec grep -q pattern {} ';'
, один вызов grep
будет выполняться для каждого файла, что значительно замедлит его работу.
Ваш первый подход будет работать в zsh
при условии, что вы заменили --color=always
на -Z
и изменили значение IFS
на IFS=$'\0'
вместо IFS=$' \r\n\0'
по умолчанию. Я бы не стал работать в других оболочках, так как они не поддерживают сохранение NUL в переменных, не говоря уже о $IFS
, а также выполняли бы генерацию имени файла для слов, полученных в результате разделения, которое вам нужно отключить с помощью set -o noglob
или set -f
.
Почему зацикливание вывода find является плохой практикой? даст вам дополнительные советы о том, как надежно обрабатывать список файлов, найденных find
.