I am trying to understand the impact of exclamation (and read) in following commands in a Makefile in a codebases I work with.

    ! gofmt -s -l . | read;
    ! go run golang.org/x/tools/cmd/goimports -l . | read;

These commands are run on Mac and other unix based systems.

A lot of the questions about exclamation mark in bash scripts mention they are for history expansion. But, in context of the above Makefile, it does not seem to make sense.

Would appreciate any help in understanding what the ! and the piped read accomplish here. Thank you!

  • Typically, ! in Linux tools breaks out to a shell. For example, in vi I can type :4,7 ! tr 'a-z' 'A-Z', which will pass lines 4 - 7 to tr on stdin, and replace them in the edit with the stdout, thereby uppercasing those lines. As the text to the right of each of your ! seems to be a shell command, I assume the line in your makefile is replaced by the output of the command, and then re-processed as makefile syntax. Commented Jul 28, 2021 at 21:47
  • Seems that the ! may be deprecated or non-Linux. GNU/make has a Shell Function command and a != operator that also return the output of an external command into the makefile itself. <www.gnu.org/software/make/manual/make.html#Shell-Function> Commented Jul 28, 2021 at 22:17
  • I think ! and | have their normal shell pipeline meanings in this context . In particular, man gofmt says that -s tries to simplify the code, while -l seems to print the filename to stdout if the result is different; since read exits successfully if it reads something, ! inverts that meaning so the rule succeeds if no file fails the gofmt -s test. I haven't looked at the second command but I suspect something similar. Commented Jul 28, 2021 at 23:13

1 Answer 1


As steeldriver surmises, this isn’t a Make construct but a shell construct: piping to read provides a test for content, and negating it provides a test for emptiness.

! command | read

succeeds if command produces no output.

You can see this without Make:

! true | read; echo $?
! echo bar | read; echo $?

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .