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

Abr*_*ile 119 makefile

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

它出什么问题了?

 if [ -a myApp ]
 then
     rm myApp
 fi
Run Code Online (Sandbox Code Playgroud)

我收到此错误消息

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

hol*_*lms 198

看到这么多人使用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 
Run Code Online (Sandbox Code Playgroud)

更新:

我发现了一种真正适用于我的方法:

ifneq ("$(wildcard $(PATH_TO_FILE))","")
    FILE_EXISTS = 1
else
    FILE_EXISTS = 0
endif
Run Code Online (Sandbox Code Playgroud)

  • 有人应该提一下,这些指令只有在没有缩进的情况下才有效... (67认同)
  • 尝试了这个,但我只是继续```Makefile:133:***未终止调用函数`wildcard':缺少`)'.Stop.``` (3认同)
  • 也有助于理解 `$(wildcard pattern)` 的实际作用。[见链接](https://www.gnu.org/software/make/manual/html_node/Wildcard-Function.html)。 (3认同)
  • 更简洁:`FILE_EXISTS := $(或 $(and $(通配符 $(PATH_TO_FILE)),1),0)` (2认同)
  • 值得注意的是,如果您在Windows下以cygwin运行,则以这种方式使用通配符会在文件名上区分大小写,因此,如果文件存在但大小写与路径不同,则找不到该文件。似乎没有任何方法可以覆盖makefile中的此行为。 (2认同)

Mar*_*ins 48

它可能需要在行尾用反斜杠来继续(尽管这可能取决于make的版本):

if [ -a myApp ] ; \
then \
     rm myApp ; \
fi;
Run Code Online (Sandbox Code Playgroud)

  • 似乎不是Makefile语法?http://sunsite.ualberta.ca/Documentation/Gnu/make-3.79/html_chapter/make_7.html (2认同)

ken*_*orb 47

问题是当您将命令分成多行时.因此,您可以使用\行末尾的行继续,也可以使用&&bash中的运算符在一行上获取所有内容.

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

test -f myApp && echo File does exist
Run Code Online (Sandbox Code Playgroud)

-f file 如果文件存在且为常规文件,则为True.

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

或不:

test -f myApp || echo File does not exist
test ! -f myApp && echo File does not exist
Run Code Online (Sandbox Code Playgroud)

test相当于[命令.

[ -f myApp ] && rm myApp   # remove myApp if it exists
Run Code Online (Sandbox Code Playgroud)

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

请参阅:help [help test进一步的语法.

  • 我会赞成,但你并没有警告`-s`是`存在且大小大于零的特殊情况.写的问题与大小无关,因此应使用`test -e`检查文件或`-d`检查目录.空文件特别有用(因为缺少更好的术语)指标/哨兵,这可能与`make`非常相关. (3认同)
  • 为了使它起作用,您需要添加`||。最后是true,因此当文件不存在时命令将返回true。 (2认同)
  • @AndrewMackenzie `test -f myApp || CMD`,注意`||`,所以如果`-f` 会失败 - 不存在(`||`),然后运行该命令。是否有意义? (2认同)

Jer*_*oen 26

或者只是把它放在一行,就像make喜欢它:

if [ -a myApp ]; then rm myApp; fi;
Run Code Online (Sandbox Code Playgroud)

  • 错误 `/bin/sh: 1: [: -a: 意外的运算符` (4认同)

cns*_*nst 23

ifeq然而,第二个最佳答案提到,它没有提到它们必须与目标名称处于同一级别,例如,只有当目前不存在时才下载文件,可以使用以下代码:

download:
ifeq (,$(wildcard ./glob.c))
    curl … -o glob.c
endif
Run Code Online (Sandbox Code Playgroud)

  • 这个答案会有点奇怪;文件检查在 makefile 被处理时发生,但动作将在 make 构建目标时发生。如果您同时删除该文件,则不会创建该文件。我已经进行了编辑以使其更清晰。 (6认同)
  • @TarasMatsyk,我认为您实际上并不需要'if fi'部分,我想它应该演示其他内容-我不太确定它在答案中是如何结束的,TBH。¯\\ _(ツ)\ _ /¯ (2认同)

dry*_*dam 12

缺少分号

if [ -a myApp ];
then
  rm myApp
fi
Run Code Online (Sandbox Code Playgroud)

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


Rob*_*Hsu 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)
Run Code Online (Sandbox Code Playgroud)

执行结果:

bash> make
/usr/bin/perl exists.
/nofile does not exist.
Run Code Online (Sandbox Code Playgroud)


Ant*_*osa 7

一线解决方案:

   [ -f ./myfile ] && echo exists
Run Code Online (Sandbox Code Playgroud)

一线解决方案,采取错误措施:

   [ -f ./myfile ] && echo exists || echo not exists
Run Code Online (Sandbox Code Playgroud)

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

clean:
    @[ -f ./myfile ] && rm myfile || true
Run Code Online (Sandbox Code Playgroud)

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

  • 只需执行@rm -f myfile。由于“-f”标志,无论文件是否存在,“rm”都会以 0 退出。 (3认同)

小智 5

ifneq ("$(wildcard $(PATH_TO_FILE))","")
    FILE_EXISTS = 1
else
    FILE_EXISTS = 0
endif
Run Code Online (Sandbox Code Playgroud)

上面发布的这个解决方案效果最好。但请确保您没有将 PATH_TO_FILE 分配字符串化,例如,

PATH_TO_FILE = "/usr/local/lib/libhl++.a" # WILL NOT WORK
Run Code Online (Sandbox Code Playgroud)

一定是

PATH_TO_FILE = /usr/local/lib/libhl++.a
Run Code Online (Sandbox Code Playgroud)