How do I check if file exists in Makefile so I can delete it?
Solution 1
The second top answer mentions ifeq
, however, it fails to mention that this ifeq
must be at the same indentation level in the makefile as the name of the target, e.g., to download a file only if it doesn't currently exist, the following code could be used:
download:
ifeq (,$(wildcard ./glob.c))
curl … -o glob.c
endif
# THIS DOES NOT WORK!
download:
ifeq (,$(wildcard ./glob.c))
curl … -o glob.c
endif
Solution 2
It's strange to see so many people using shell scripting for this. I was looking for a way to use native makefile syntax, because I'm writing this outside of any target. You can use the wildcard
function to check if file exists:
ifeq ($(UNAME),Darwin)
SHELL := /opt/local/bin/bash
OS_X := true
else ifneq (,$(wildcard /etc/redhat-release))
OS_RHEL := true
else
OS_DEB := true
SHELL := /bin/bash
endif
Update:
I found a way which is really working for me:
ifneq ("$(wildcard $(PATH_TO_FILE))","")
FILE_EXISTS = 1
else
FILE_EXISTS = 0
endif
Solution 3
The problem is when you split your command over multiple lines. So, you can either use the \
at the end of lines for continuation as above or you can get everything on one line with the &&
operator in bash.
Then you can use a test
command to test if the file does exist, e.g.:
test -f myApp && echo File does exist
-f file
True if file exists and is a regular file.
-s file
True if file exists and has a size greater than zero.
or does not:
test -f myApp || echo File does not exist
test ! -f myApp && echo File does not exist
The test
is equivalent to [
command.
[ -f myApp ] && rm myApp # remove myApp if it exists
and it would work as in your original example.
See: help [
or help test
for further syntax.
Solution 4
It may need a backslash on the end of the line for continuation (although perhaps that depends on the version of make):
if [ -a myApp ] ; \
then \
rm myApp ; \
fi;
Solution 5
Or just put it on one line, as make
likes it:
if [ -a myApp ]; then rm myApp; fi;
Related videos on Youtube

Abruzzo Forte e Gentile
Updated on February 04, 2022Comments
-
Abruzzo Forte e Gentile 11 months
In the clean section of my
Makefile
I am trying to check if the file exists before deleting permanently. I use this code but I receive errors.What's wrong with it?
if [ -a myApp ] then rm myApp fi
I get this error message
if [ -a myApp ] /bin/sh: Syntax error: end of file unexpected (expecting "then") make: *** [clean] Error 2
-
thomasa88 almost 9 yearsIf you just want to avoid make stopping if the file does not exist,
rm -rf myApp
could be an alternative. Or preceding the command with a dash (-rm myApp
) to make make ignore the error from rm (it will however print an ugly message). -
Michael almost 4 yearsYour problem was that make treats each line in a rule as a separate command and sends them individually to the shell. It's like running just `if [ -a myApp ]' on its own. If you get this error you either need a solution which joins the lines into one (using ) or which ends up with each line independent of the other. There are now several of these below.
-
-
Abruzzo Forte e Gentile over 11 yearsThHat's exactly what I wanted to do. Thanks a lot.
-
holms about 9 yearsseems to be not a Makefile syntax? sunsite.ualberta.ca/Documentation/Gnu/make-3.79/html_chapter/…
-
holms almost 9 yearsI've got actually alternative variant recently. I'm discovering package managers with this
yum := $(shell { type yum; } 2>/dev/null)
and withifdef
you can check if variable empty or not, and then set something likeRHEL:=true
-
Ant6n about 8 yearstried this, but I just keep getting
Makefile:133: *** unterminated call to function `wildcard': missing `)'. Stop.
-
flungo about 8 years@holms its a bash syntax. By escaping the new lines it allows it to be handled as a single bash command. By default in
make
a new line would be a new bash command. The major caveat of this, other than the annoyance of having lots of\
at the end of lines is that every command must be terminated with the;
which would otherwise be implicit in bash. -
tom_mai78101 almost 8 years@arsenbonbon Your comment really helps. Appreciated.
-
tom_mai78101 almost 8 years@Ant6n You might be missing a parentheses. Please check.
-
Maitreya over 7 yearsThe right answer is by @holms. Neither '\' nor wildcard is exactly intended for this purpose. The reason why you would use wildcard is for code clarity. Not only is this method less readable, it's more prone to syntax errors.
-
underscore_d over 7 yearsI would have upvoted, but you did not warn that
-s
is a special case forexists and has a size greater than zero
. The question as written is size-agnostic, so existence should be checked usingtest -e
for a file or-d
for a directory. Empty files can be especially useful as (for want of a better term) indicators/sentinels, which might be quite relevant formake
. -
glerYbo over 7 yearsThanks for the suggestion. Changed
-f
by default, as it's more common to use. -
thowa almost 7 yearsHow can I get
test
on Windows? -
fero over 6 yearsthe link @holms provided does not work anymore, use gnu.org/software/make/manual/make.html#Conditionals instead
-
serup over 6 yearsThis I could get to work on one line in make file like this: @ test -f file && echo file exist -- however I could not get the other examples to work
-
Christopher over 6 yearsThis fails if $(PATH_TO_FILE) evaluates to a filename containing parentheses.
-
Alexey Polonsky about 6 yearsjust do @rm -f myfile. Because of the "-f" flag, "rm" will exit with 0 regardless of whether the file exists or not.
-
anoop over 5 yearsGreat use of wildcard, so it can be done with makefile itself. Neat :)
-
jcubic almost 5 yearsIn order for this to work you need to add
|| true
at the end so the command return true when file don't exists. -
alexpanter over 4 yearsThis answer should be upvoted as it is easy, simple, one-line, and solves the problem.
-
Dr. Dan about 4 yearsHelps to also understand what
$(wildcard pattern)
actually does. See link. -
Danijel about 4 yearsIs there a way to make this work within a make rule (when "indented")?
-
cmaster - reinstate monica about 4 yearsMore concise:
FILE_EXISTS := $(or $(and $(wildcard $(PATH_TO_FILE)),1),0)
-
Roger Sanders about 4 yearsIt's worth noting if you're running on Windows under cygwin, using wildcard in this manner does a case sensitive match on the filename, so if the file exists but with different case than the path it won't be found. There doesn't seem to be any way to override this behaviour within the makefile.
-
taras almost 4 yearsdid not work until I added backslash `` after if fi
-
Victor Sergienko almost 4 years
directives only work if they're not indented
with tabs. Plus, they run at makefile parsing stage, not in "runtime" (target execution) stage. -
Michael almost 4 yearsThis answer will be a bit weird; the file check happens when the makefile is processed but the action will happen later when the target is built by make. If you delete the file in the meantime then the file won't be created. I have put in an edit to make it clearer.
-
Michael almost 4 yearsthis is a great answer because it matches what is wrong with what the original questioner did and it will work depending on whether the file exists at the time the target is build rather than at the time the Makefile is started which is what most people would expect and want most of the time. In a few weird cases the answer from @cnst would be better.
-
Michael almost 4 yearsthat's a great answer in this case (and should get upvotes) but won't work so well if the actions were more complex, in which case just switch to using \
-
Michael almost 4 yearsthis won't work in a Makefile because the if is still spread over multiple lines - you need to either put this on one line or use \es. and even if you added the \ es you are still missing some semi-colons.
-
cnst almost 4 yearsThis is a good answer for deleting the file that the OP had, but I'm pretty sure most people who find this question aren't actually looking for deleting any files; this is actually evidenced by the fact that most answers don't even mention
rm
at all; BTW, I'm pretty sure thatrm -f /$(myAppPath)
won't do any damage, either, because/
is a directory, and the-r
is missing. -
glerYbo almost 4 years@AndrewMackenzie
test -f myApp || CMD
, notice the||
, so if-f
will fail - does not exist (||
), then run the command. Does it make sense? -
Robin Hsu almost 4 years[ -a myApp ] && rm myApp
-
Jesse Chisholm over 3 yearsThe original question, and this answer are attacking it at the
inside an action command
phase, whereas the @holms answer is attacking it at themakefile parsing
phase. So which answer is best depends on what you need. -
Jesse Chisholm over 3 yearsOr,
-rm myfile
the lead dash telling make to ignore any error. -
Flic over 3 yearsIn my case, leaving off the || <error action> caused problems. Your final example, where you returned true if the file did not exist, addressed this nicely. Thank you!
-
Kevin Buchs over 3 yearsThanks much! This point was not clear from reading the manual.
-
Sten about 3 yearsFor me path to myfile needs to be with apostrophe('):
@[ -f 'myfile' ] && rm myfile
-
dancow about 3 yearsThis is not a simpler solution. Like @cnst said, there may be reasons why the original poster does not simply want to do an
rm -f
, e.g. they may want torm
a variable. -
Peter Krauss almost 2 yearsERROR
/bin/sh: 1: [: -a: unexpected operator
-
Chan Kim over 1 yearI like this simple answer. if the file exists delete, if it doesn't exist, don't complain!
-
nathanchere about 1 yearThis does not work in a makefile. It ill always run the
rm -rf FILENAME
regardless of the firsttest
result