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
This question is related to
makefile
test ! -f README.md || echo 'Support OpenSource!' >> README.md
"If README.md does not exist, do nothing (and exit successfully). Otherwise, append text to the end."
If you use &&
instead of ||
then you generate an error when the file doesn't exist:
Makefile:42: recipe for target 'dostuff' failed
make: *** [dostuff] Error 1
Or just put it on one line, as make
likes it:
if [ -a myApp ]; then rm myApp; fi;
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.
The answers like the one from @mark-wilkins using \ to continue lines and ; to terminate them in the shell or like the ones from @kenorb changing this to one line are good and will fix this problem.
there's a simpler answer to the original problem (as @alexey-polonsky pointed out). Use the -f flag to rm so that it won't trigger an error
rm -f myApp
this is simpler, faster and more reliable. Just be careful not to end up with a slash and an empty variable
rm -f /$(myAppPath) #NEVER DO THIS
you might end up deleting your system.
I was trying:
[ -f $(PROGRAM) ] && cp -f $(PROGRAM) $(INSTALLDIR)
And the positive case worked but my ubuntu bash shell calls this TRUE and breaks on the copy:
[ -f ] && cp -f /home/user/proto/../bin/
cp: missing destination file operand after '/home/user/proto/../bin/'
After getting this error, I google how to check if a file exists in make, and this is the answer...
One line solution:
[ -f ./myfile ] && echo exists
One line solution with error action:
[ -f ./myfile ] && echo exists || echo not exists
Example used in my make clean
directives:
clean:
@[ -f ./myfile ] && rm myfile || true
And make clean
works without error messages!
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
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;
FILE1 = /usr/bin/perl
FILE2 = /nofile
ifeq ($(shell test -e $(FILE1) && echo -n yes),yes)
RESULT1=$(FILE1) exists.
else
RESULT1=$(FILE1) does not exist.
endif
ifeq ($(shell test -e $(FILE2) && echo -n yes),yes)
RESULT2=$(FILE2) exists.
else
RESULT2=$(FILE2) does not exist.
endif
all:
@echo $(RESULT1)
@echo $(RESULT2)
execution results:
bash> make
/usr/bin/perl exists.
/nofile does not exist.
ifneq ("$(wildcard $(PATH_TO_FILE))","")
FILE_EXISTS = 1
else
FILE_EXISTS = 0
endif
This solution posted above works best. But make sure that you do not stringify the PATH_TO_FILE assignment E.g.,
PATH_TO_FILE = "/usr/local/lib/libhl++.a" # WILL NOT WORK
It must be
PATH_TO_FILE = /usr/local/lib/libhl++.a
Missing a semicolon
if [ -a myApp ];
then
rm myApp
fi
However, I assume you are checking for existence before deletion to prevent an error message. If so, you can just use rm -f myApp
which "forces" delete, i.e. doesn't error out if the file didn't exist.
Source: Stackoverflow.com