264

I wrote a program for an assignment which is supposed to print its output to stdout. The assignment spec requires the creation of a Makefile which when invoked as make run > outputFile should run the program and write the output to a file, which has a SHA1 fingerprint identical to the one given in the spec.

My problem is that my makefile:

...
run:
     java myprogram

also prints the command which runs my program (e.g. java myprogram) to the output file, so that my file includes this extra line causing the fingerprint to be wrong.

Is there any way to execute a command without the command invocation echoing to the command line?

zed_0xff
  • 32,417
  • 7
  • 53
  • 72
noobler
  • 3,495
  • 4
  • 22
  • 26
  • Great question, and great answers, though I would like to note that `make` is really intended to "make" files. So rather than `make run > outputFile`, a more appropriate use would, technically, be `make outputFile`, and the command would be `java myprogram > outputFile`. If you want it to _always_ run, then use `.PHONY`. I think `.SILENT` is a great answer if used that way because `make -v` would let you see the command used to generate it without affecting the output. The `@` prefix is a better answer if used the way you asked (with `> ouputFile`) – redbmk Aug 05 '23 at 00:00
  • That said, I've used the phony usage more often in practice and tend to add `.PHONY: *` to the top of the file ¯\\_(ツ)_/¯ – redbmk Aug 05 '23 at 00:03

4 Answers4

428

Add @ to the beginning of command to tell gmake not to print the command being executed. Like this:

run:
     @java myprogram

As Oli suggested, this is a feature of Make and not of Bash.

On the other hand, Bash will never echo commands being executed unless you tell it to do so explicitly (i.e. with -x option).

  • 11
    +1. But just to clear up the OP's confusion, it's perhaps worth clarifying that this is a feature of Make, not of Bash. – Oliver Charlesworth Apr 01 '12 at 18:42
  • Is there a way of disabling all echos? Or of turning it off for a section, and back on later? – Benubird Apr 22 '15 at 07:58
  • 4
    @Benubird `make -s` does that, and IMHO is a much better solution here anyway. It was recently posted as a separate answer to this question. – tripleee Feb 17 '16 at 08:51
  • 1
    this doesn't work for an if ... then statement :( any ideas? – user1623521 May 09 '16 at 10:12
  • 1
    IMO this is not good advice. No recipe line that does anything more complex than an `echo` should ever be prefixed by `@`. It makes debugging makefiles extremely difficult and time-consuming. The right answer is to use the `.SILENT:` special target, which can be overridden via the command line when you do want to see the commands. – MadScientist Apr 04 '18 at 15:09
  • "-x" is an invalid option.. there is no such option as "-x" – MSharq May 25 '19 at 11:21
  • if the command fails make still see that error right? @ suppresses output but not return code right? – red888 Sep 18 '19 at 23:30
  • @MSharq: `bash -xc 'echo hi'` prints "+ echo hi" on one line and "hi" on another – redbmk Aug 05 '23 at 00:10
143

Even simpler, use make -s (silent mode)!

Ed The ''Pro''
  • 875
  • 10
  • 22
user3619296
  • 1,607
  • 1
  • 11
  • 3
  • 8
    Upvote: This should really be the accepted answer here. Sprinkling your Makefile with `@` commands makes it hard to debug and adds a lot of clutter. – tripleee Feb 17 '16 at 08:52
  • 28
    I agree this is the way to go - but notice, in the original problem description, I wouldn't be the one invoking make - my instructor would be. Thus, I would have no control over the flags passed in. I needed to control the output from within the makefile. Upvote for most practical solution in the real world though. – noobler Feb 17 '16 at 14:30
  • 14
    You can control this yourself, using the `.SILENT:` target. See http://make.mad-scientist.net/managing-recipe-echoing/ – MadScientist Apr 04 '18 at 15:07
  • Actually if you have warnings on like `-Wall` it still prints them. Of course why would you use `-s` if you want to see warnings too? – If_You_Say_So May 14 '20 at 17:35
  • I disagree that this should be the accepted answer. The person who asked wanted to suppress a single command not all commands. This is still a useful piece of information but it suppresses all commands which is not what was asked for. – shawn1874 Jun 02 '22 at 17:28
87

You can also use .SILENT

.SILENT: run
hi:
     echo "Hola!"
run:
     java myprogram

In this case, make hi will output command, but make run will not output.

Andrei Savin
  • 2,350
  • 4
  • 26
  • 40
Kien Pham
  • 2,679
  • 2
  • 23
  • 23
6

The effect of preceding the command with an @ can be extended to a section by extending the command using a trailing backslash on the line. If a .PHONY command is desired to suppress output one can begin the section with:

@printf "..."
Ed The ''Pro''
  • 875
  • 10
  • 22
Wiley
  • 506
  • 5
  • 4