[bash] How can I use Bash syntax in Makefile targets?

I often find Bash syntax very helpful, e.g. process substitution like in diff <(sort file1) <(sort file2).

Is it possible to use such Bash commands in a Makefile? I'm thinking of something like this:

file-differences:
    diff <(sort file1) <(sort file2) > $@

In my GNU Make 3.80 this will give an error since it uses the shell instead of bash to execute the commands.

This question is related to bash shell makefile

The answer is


One way that also works is putting it this way in the first line of the your target:

your-target: $(eval SHELL:=/bin/bash)
    @echo "here shell is $$0"

If portability is important you may not want to depend on a specific shell in your Makefile. Not all environments have bash available.


There is a way to do this without explicitly setting your SHELL variable to point to bash. This can be useful if you have many makefiles since SHELL isn't inherited by subsequent makefiles or taken from the environment. You also need to be sure that anyone who compiles your code configures their system this way.

If you run sudo dpkg-reconfigure dash and answer 'no' to the prompt, your system will not use dash as the default shell. It will then point to bash (at least in Ubuntu). Note that using dash as your system shell is a bit more efficient though.


You can call bash directly, use the -c flag:

bash -c "diff <(sort file1) <(sort file2) > $@"

Of course, you may not be able to redirect to the variable $@, but when I tried to do this, I got -bash: $@: ambiguous redirect as an error message, so you may want to look into that before you get too into this (though I'm using bash 3.2.something, so maybe yours works differently).


You can call bash directly within your Makefile instead of using the default shell:

bash -c "ls -al"

instead of:

ls -al

Examples related to bash

Comparing a variable with a string python not working when redirecting from bash script Zipping a file in bash fails How do I prevent Conda from activating the base environment by default? Get first line of a shell command's output Fixing a systemd service 203/EXEC failure (no such file or directory) /bin/sh: apt-get: not found VSCode Change Default Terminal Run bash command on jenkins pipeline How to check if the docker engine and a docker container are running? How to switch Python versions in Terminal?

Examples related to shell

Comparing a variable with a string python not working when redirecting from bash script Get first line of a shell command's output How to run shell script file using nodejs? Run bash command on jenkins pipeline Way to create multiline comments in Bash? How to do multiline shell script in Ansible How to check if a file exists in a shell script How to check if an environment variable exists and get its value? Curl to return http status code along with the response docker entrypoint running bash script gets "permission denied"

Examples related to makefile

MINGW64 "make build" error: "bash: make: command not found" "No rule to make target 'install'"... But Makefile exists How to overcome "'aclocal-1.15' is missing on your system" warning? How to install and use "make" in Windows? How to get a shell environment variable in a makefile? Using local makefile for CLion instead of CMake Difference between using Makefile and CMake to compile the code How to set child process' environment variable in Makefile Windows 7 - 'make' is not recognized as an internal or external command, operable program or batch file Debugging the error "gcc: error: x86_64-linux-gnu-gcc: No such file or directory"