Можно исключить файлы _test.go
при использовании go run
через командную строку (MacOS).
go run $(ls -1 dir/*.go | grep -v _test.go)
Однако похоже, что команда не используется аналогичным образом через make-файл Go. Например,
start:
go run $(ls -1 dir/*.go | grep -v _test.go)
и
start:
go run `$(ls -1 dir/\*.go | grep -v _test.go)`
оба результата
go run: no go files listed
Как правильно использовать grep
и подобные команды в make-файле Go?
Знаки доллара делают особенным: они вводят переменные и функции make. Если вы хотите использовать буквальный знак доллара в своем рецепте, вам нужно избежать его, удвоив его:
start:
go run $$(ls -1 dir/*.go | grep -v _test.go)
Как уже упоминалось в другом ответе, тривиальным решением является удвоение всех знаков доллара, чтобы Make не попытался интерпретировать их как переменные или функции Make. Точно так же вы можете использовать устаревший синтаксис подстановки команд `ls ... stuff`
с обратными кавычками вместо$(ls ... stuff)
Однако этот подход более принципиально ошибочен в том, что он спускается в глубокое болото угловых случаев, влияющих на разбор вывода ls
. Более надежный подход - использовать функции Make для выражения шаблона.
go run $(filter-out %_test.go,$(wildcard dir/*.go))
Я также упомяну, что в Bash есть функция под названием расширенная подстановка (google extglob
), где вы можете сказать что-то вроде !(dir/*_test.go)dir/*.go
, чтобы исключить набор файлов из совпадений с подстановочными знаками. Но вы, вероятно, не хотите нарушать переносимость вашего Makefile, когда Make имеет встроенную функциональность, которая обеспечивает ту же функциональность (хотя и с более подробным синтаксисом. На самом деле это функция, потому что она упрощает для нового сопровождающего погуглите имена функций и выясните, что делает код!)
Следует ли обрезать префикс dir/
спереди, думаю, ls
это делает ...? Есть функция Make $(notdir ...)
, которую можно обернуть вокруг вызова $(wildcard ...)
.
Я предполагаю, что вы уловили намерение OP, но, технически говоря, $(filter-out %_test.go,...
не эквивалентен grep -v _test.go
, потому что он не улавливает foo_test.gobar
, в то время как grep
делает.
@RenaudPacalet Я бы назвал это функцией, а не ошибкой, но да, вы технически правы и, конечно, это может иметь значение. (grep -v _test.go
также удаляет it_testago.go
.)
Я не возражаю, что использование функций make - лучшая идея, но я не уверен, что это решает многие проблемы, связанные с использованием вывода ls
. В конце концов, make тоже не «правильно» обрабатывает имена файлов, содержащие пробелы.
Это правда; make
гораздо более требователен, чем оболочка, поэтому для написания действительного Makefile вам необходимо наложить ограничения на имена файлов, которые устраняют многие опасности синтаксического анализа вывода ls
.
Вы можете использовать обратные кавычки вместо
$(ls ...)
- использование обоих внутри друг друга означает «взять выводls
и запустите это как команду» (но этого не произошло, потому что вам все равно нужно удвоить знак доллара).