如何检查Makefile中是否存在文件,以便删除它?

时间:2011-04-05 14:17:36

标签: makefile

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

它出了什么问题?

 if [ -a myApp ]
 then
     rm myApp
 fi

我收到此错误消息

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

14 个答案:

答案 0 :(得分:185)

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

 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 

更新

我找到了一种真正适合我的方式:

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

答案 1 :(得分:47)

在行尾可能需要反斜杠才能继续(虽然这可能取决于make的版本):

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

答案 2 :(得分:41)

问题在于您将命令分成多行。因此,您可以使用行末尾的\进行连续,也可以使用bash中的&&运算符将所有内容放在一行上。

然后,您可以使用test命令来测试文件是否存在,例如:

test -f myApp && echo File does exist
  

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

     

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

或不:

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

test等同于[命令。

[ -f myApp ] && rm myApp   # remove myApp if it exists

它会像你原来的例子一样工作。

有关更多语法,请参阅:help [help test

答案 3 :(得分:25)

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

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

答案 4 :(得分:18)

第二个最佳答案提及ifeq,但是,它没有提到这些必须与目标名称处于同一级别,例如,仅在目前没有文件时才下载文件存在,可以使用以下代码:

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

答案 5 :(得分:12)

缺少分号

if [ -a myApp ];
then
  rm myApp
fi

但是,我假设您在删除之前检查是否存在以防止出现错误消息。如果是这样,您可以使用“强制”删除rm -f myApp,即如果文件不存在则不会出错。

答案 6 :(得分:11)

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.

答案 7 :(得分:5)

一线解决方案:

   [ -f ./myfile ] && echo exists

包含错误操作的一行解决方案:

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

我的make clean指令中使用的示例:

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

make clean总是有效,没有任何错误消息!

答案 8 :(得分:0)

类似于@ mark-wilkins的答案,使用\继续行和;在shell中终止它们或像@kenorb中的将它们更改为一行一样是好的,它将解决此问题。

对于原始问题有一个更简单的答案(如@ alexey-polonsky所指出的)。使用-f标志来rm,使其不会触发错误

rm -f myApp

这更简单,更快,更可靠。请注意不要以斜杠和空变量结尾

rm -f / $(myAppPath)#从不这样做

您可能最终会删除系统。

答案 9 :(得分:0)

test ! -f README.md || echo 'Support OpenSource!' >> README.md

“如果README.md不存在,则不执行任何操作(并成功退出)。否则,将文本追加到末尾。”

如果使用&&而不是||,则在文件不存在时会产生错误:

Makefile:42: recipe for target 'dostuff' failed
make: *** [dostuff] Error 1

答案 10 :(得分:0)

我正在尝试:

[ -f $(PROGRAM) ] && cp -f $(PROGRAM) $(INSTALLDIR)

积极的情况奏效,但我的ubuntu bash shell将此称为TRUE并在副本上中断了:

[ -f  ] && cp -f  /home/user/proto/../bin/
cp: missing destination file operand after '/home/user/proto/../bin/'

收到此错误后,我用谷歌搜索了如何检查make中是否存在文件,这就是答案...

答案 11 :(得分:0)

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

以上发布的此解决方案效果最好。但是请确保您不对PATH_TO_FILE分配进行字符串化 例如,

PATH_TO_FILE = "/usr/local/lib/libhl++.a" # WILL NOT WORK

必须是

PATH_TO_FILE = /usr/local/lib/libhl++.a

答案 12 :(得分:0)

与问题略有不同,但如果您有一个包含要删除的文件列表的变量,您可以执行

targets: filename1 filename2

clean_targets:
    @$(foreach file, $(targets), test -f $(file) && rm -v $(file) || echo No $(file);)

基本上你遍历由目标变量定义的文件名,并检查目标是否存在。如果是,删除该文件,如果不是,则报告它不存在。最后一次检查(报告它不存在)是必要的,否则会在根本没有目标的情况下引发错误

答案 13 :(得分:0)

使用test命令检查文件是否存在,然后使用rm删除它。\

文件命令的语法是 -

test -f FILENAME && echo exists || echo not exists

删除文件的语法是 -

rm -rf FILENAME

所以现在我们需要一个命令来删除文件,只有当它存在时,我们将只使用 OR || 和 test 命令

test -f FILENAME || rm -rf FILENAME

use 可以通过在括号 && 中使用和 () 来使用多个命令

test -f FILENAME || (rm -rf FILENAME && echo "file deleted as it exists")