2011-04-05 102 views
91

在makefle的干净部分,我试图在永久删除之前检查文件是否存在。我使用此代码,但我收到错误。如何检查Makefile中是否存在文件?

它有什么问题?

if [ -a myApp ] 
then 
    rm myApp 
fi 

我收到此错误信息

f [ -a myApp ] 
/bin/sh: Syntax error: end of file unexpected (expecting "then") 
make: *** [clean] Error 2 
+0

myApp是变量还是实际文件名? – BugFinder 2011-04-05 14:21:47

+0

myApp适用于myApplication,即构建过程的文件名。 – 2011-04-05 15:31:00

+5

如果你只是想避免停止,如果该文件不存在,'rm -rf myApp'可以替代。或者在命令前加一个短划线('-rm myApp')来使得忽略来自rm的错误(然而它会打印一个丑陋的消息)。 – thomasa88 2014-01-06 09:10:14

回答

1

第二顶答案提到ifeq,但是,它没有提到这些都必须在同一水平作为目标,如名称,下载文件只有当前不存在时,才可以使用以下代码:

if fi 
download: 
ifeq (,$(wildcard ./glob.c)) 
    curl … -o glob.c 
endif 
13

缺少一个分号

if [ -a myApp ]; 
then 
    rm myApp 
fi 

不过,我以为你是检查是否存在在删除前,防止错误信息。如果是这样,您可以使用rm -f myApp这些“强制”删除,即如果文件不存在则不会出错。

+1

ThHat正是我想要做的。非常感谢。 – 2011-04-05 15:31:54

47

这可能需要对延续行的末尾反斜杠(虽然可能依赖于版本的make):

if [ -a myApp ] ; \ 
then \ 
    rm myApp ; \ 
fi; 
+2

似乎不是Makefile语法? http://sunsite.ualberta.ca/Documentation/Gnu/make-3.79/html_chapter/make_7.html – holms 2013-12-13 12:39:42

+0

@holms它的bash语法。通过转义新行,它允许将它作为单个bash命令处理。默认情况下,在'make'中,新行将是一个新的bash命令。这个主要的警告,除了在行尾有大量'\'的烦恼之外,每个命令都必须以';'结尾,否则这些命令将隐含在bash中。 – flungo 2014-12-10 08:51:29

+1

正确的答案是@holms。 “\”和通配符都不是用于此目的。你使用通配符的原因是为了代码清晰。这种方法不仅可读性较差,而且更容易出现语法错误。 – Maitreya 2015-04-25 00:15:48

19

或者只是把它在同一行,因为make喜欢它:

if [ -a myApp ]; then rm myApp; fi; 
148

看到有这么多人使用shell脚本,这很奇怪。我正在寻找一种使用本地makefile语法的方式,因为我在任何目标之外编写这个语法。您可以使用wildcard函数来检查文件是否存在:

ifeq ($(UNAME),Darwin) 
    SHELL := /opt/local/bin/bash 
    OS_X := true 
else ifeq (,$(wildcard /etc/redhat-release)) 
    OS_RHEL := true 
else 
    OS_DEB := true 
    SHELL := /bin/bash 
endif 

更新:

我找到了一种方法,其是真正为我工作:

ifneq ("$(wildcard $(PATH_TO_FILE))","") 
FILE_EXISTS = 1 
else 
FILE_EXISTS = 0 
endif 
+1

巧妙的技巧。我只是要检查gentoo发布:) – thomasa88 2014-01-06 09:11:02

+0

我最近有实际的替代变种。我用这个'yum:= $(shell {type yum;} 2>/dev/null)'来发现软件包管理器,并用'ifdef'来检查变量是否为空,然后设置类似'RHEL: = true' – holms 2014-02-26 03:16:32

+39

有人应该提到,指令只有在它们没有缩进时才起作用...... – arsenbonbon 2014-03-26 13:47:34

23

您可以简单地使用test命令测试文件是否存在,例如:

test -f myApp && echo File does exist 

-f file如果文件存在并且是常规文件,则为true。

-s file如果文件存在并且大小大于零,则为true。

或不:

test -f myApp || echo File does not exist 
test ! -f myApp && echo File does not exist 

test相当于[命令。有关更多语法,请参阅:help [help test

+1

我会upvoted,但你没有警告说'-s'是'存在的特殊情况,并有一个大于零的大小。所写的问题与大小无关,因此应该使用'test -e'来检查文件,或者使用-d来检查目录。空文件可能特别有用,因为(对于更好的术语来说)指示符/哨兵,这可能与'make'非常相关。 – 2015-09-14 22:07:47

+0

感谢您的建议。默认更改'-f',因为它更常用。 – kenorb 2015-09-14 22:59:31

+0

如何在Windows上获得'test'? – thowa 2016-02-04 08:49:08

3

一号线的解决方案:

[ -f ./myfile ] && echo exists || echo not exists 

例如在我make clean指令用于:

错误动作
[ -f ./myfile ] && echo exists 

一号线解决方案

clean: 
    @[ -f ./myfile ] && rm myfile || true 

而且make clean总是工作没有任何错误消息!

+0

只是做@rm -f myfile。由于“-f”标志,无论文件是否存在,“rm”都将以0退出。 – 2016-11-15 14:21:25

5
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) 

执行结果:

bash> make 
/usr/bin/perl exists. 
/nofile does not exist.