bash 测试目录是否存在于 makefile 中

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20763629/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 00:34:08  来源:igfitidea点击:

Test whether a directory exists inside a makefile

bashmakefile

提问by Dror

In his answer@Grundlefleck explains how to check whether a directory exists or not. I tried some to use this inside a makefileas follow:

@Grundlefleck在他的回答中解释了如何检查目录是否存在。我尝试了一些在 a 中使用它makefile,如下所示:

foo.bak: foo.bar
    echo "foo"
    if [ -d "~/Dropbox" ]; then
        echo "Dir exists"
    fi

Running make foo.bak(given that foo.barexists) yields the following error:

运行make foo.bak(假设foo.bar存在)会产生以下错误:

echo "foo"
foo
if [ -d "~/Dropbox" ]; then
/bin/sh: -c: line 1: syntax error: unexpected end of file
make: *** [foo.bak] Error 2

The workaround I made was to have a standalone bash script where the test is implemented and I called the script from the makefile. This, however, sounds very cumbersome. Is there a nicer way to check whether a directory exists from within a makefile?

我所做的解决方法是使用一个独立的 bash 脚本来实现测试,然后我从makefile. 然而,这听起来非常麻烦。有没有更好的方法来检查目录中是否存在makefile

回答by lurker

Make commands, if a shell command, must be in one line, or be on multiple lines using a backslash for line extension. So, this approach will work:

如果是 shell 命令,make 命令必须在一行中,或者在多行中使用反斜杠进行行扩展。因此,这种方法将起作用:

foo.bak: foo.bar
    echo "foo"
    if [ -d "~/Dropbox" ]; then echo "Dir exists"; fi

Or

或者

foo.bak: foo.bar
    echo "foo"
    if [ -d "~/Dropbox" ]; then \
        echo "Dir exists"; \
    fi

回答by cforbish

This approach functions with minimal echos:

这种方法以最小的回声起作用:

.PHONY: all
all:
ifneq ($(wildcard ~/Dropbox/.*),)
        @echo "Found ~/Dropbox."
else
        @echo "Did not find ~/Dropbox."
endif

回答by Anne van Rossum

Act upon the absence of a directory

在没有目录时采取行动

If you only need to know if a directory does not exist and want to act upon that by for example creating it, you can use ordinary Makefile targets:

如果您只需要知道某个目录是否不存在并希望通过例如创建它来对其进行操作,则可以使用普通的 Makefile 目标:

directory = ~/Dropbox

all: | $(directory)
    @echo "Continuation regardless of existence of ~/Dropbox"

$(directory):
    @echo "Folder $(directory) does not exist"
    mkdir -p $@

.PHONY: all

Remarks:

评论:

  • The |indicates that make shouldn't care about the timestamp (it's an order-only-prerequisite).
  • Rather than write mkdir -p $@, you can write falseto exit, or solve your case differently.
  • |指示,使不应该关心的时间戳(这是一个订单只-的先决条件)。
  • mkdir -p $@您可以写入false退出或以不同的方式解决您的案例,而不是 write 。

If you also need to run a particular series of instructions upon the existenceof a directory, you cannot use the above. In other words, it is equivalent to:

如果您还需要在目录存在时运行特定系列的指令,则不能使用上述指令。换句话说,它等价于:

if [ ! -d "~/Dropbox" ]; then
    echo "The ~/Dropbox folder does not exist"
fi

There is no elsestatement.

没有else声明。

Act upon the presence of a directory

根据目录的存在采取行动

If you want the opposite if-statement this is also possible:

如果您想要相反的 if 语句,这也是可能的:

directory = $(wildcard ~/Dropbox)

all: | $(directory)
    @echo "Continuation regardless of existence of ~/Dropbox"

$(directory):
    @echo "Folder $(directory) exists"

.PHONY: all $(directory)

This is equivalent to:

这相当于:

if [ -d "~/Dropbox" ]; then
    echo "The ~/Dropbox folder does exist"
fi

Again, there is no elsestatement.

再次,没有else声明。

Act upon both the presence and the absence of a directory

对目录的存在和不存在都采取行动

This becomes a bit more cumbersome, but in the end gives you nice targets for both cases:

这变得有点麻烦,但最终为您提供了两种情况下的不错目标:

directory = ~/Dropbox
dir_target = $(directory)-$(wildcard $(directory))
dir_present = $(directory)-$(directory)
dir_absent = $(directory)-

all: | $(dir_target)
    @echo "Continuation regardless of existence of ~/Dropbox"

$(dir_present):
    @echo "Folder $(directory) exists"

$(dir_absent):
    @echo "Folder $(directory) does not exist"

.PHONY: all

This is equivalent to:

这相当于:

if [ -d "~/Dropbox" ]; then
    echo "The ~/Dropbox folder does exist"
else
    echo "The ~/Dropbox folder does not exist"
fi

Naturally, the wildcard expansion might be slower than an if-else-statement. However, the third case is probably quite rare and is just added for completeness.

自然地,通配符扩展可能比 if-else 语句慢。但是,第三种情况可能非常罕见,只是为了完整性而添加。

回答by Anne van Rossum

Try this:

尝试这个:

.PHONY: all
something:
    echo "hi"
all:
    test -d "Documents" && something

This will execute the commands under somethingonly if Documentsexists.

这将something仅在Documents存在时执行下面的命令。

In order to address the problemnoted in the comments, you can make a variable like this:

为了解决评论中提到的问题,您可以创建一个这样的变量:

PATH_TEST = ~/SomeDirectory

test -d $(PATH_TEST) && something

回答by fuenfundachtzig

I had a case where I wanted to define a variable based on the test whether a directory exists or not at the top-most levelof the Makefilewhere the approaches described above don't work. I found herea nice solution which can be used like this:

我有,我想在一个目录是否存在与否来定义基于测试变量的情况下,最顶层Makefile,其中的途径上述不起作用。我在这里找到一个很好的解决方案,可以这样使用:

MY_DIRNAME=../External
ifneq "$(wildcard $(MY_DIRNAME) )" ""
  # if directory MY_DIRNAME exists:
  INCLUDES += -I../External
else
  # if it doesn't:
  INCLUDES += -I$(HOME)/Code/External
endif

This will modify the variable INCLUDESbased on whether the directory stored in MY_DIRNAMEexists or not.

这将INCLUDES根据存储的目录是否MY_DIRNAME存在来修改变量。

(Motivation: In my case this variable would be used in another Makefileincluded later by the first:

(动机:在我的情况下,这个变量将在第一个Makefile稍后包含的另一个变量中使用:

include $(SFRAME_DIR)/Makefile.common

I wanted to have the same Makefilework in two different environments in a simple way.)

我想以Makefile一种简单的方式在两个不同的环境中进行相同的工作。)

回答by Anne van Rossum

There is a very different answer that allows you to use your ifstatements as you envisioned them in one shell:

有一个非常不同的答案,它允许您if在一个 shell 中使用您设想的语句:

.ONESHELL:
foo.bak: foo.bar
    echo "foo"
    if [ -d "~/Dropbox" ]; then
        echo "Dir exists"
    fi

Note that the only difference is the ONESHELL special target.

请注意,唯一的区别是 ONESHELL特殊目标

回答by user3020921

I use the following to detect if a file or a directory exists and act upon it :

我使用以下内容来检测文件或目录是否存在并对其采取行动:

$(if $(filter expected,$(wildcard *)), the expected file exists)

With your request :

根据您的要求:

.PHONY: ~/Dropbox

~/Dropbox:
    echo "Dir exists"

foo.bak: foo.bar | $(if $(filter ~/Dropbox,$(wildcard ~/*)), the expected file exists)

Which can further be simplify :

这可以进一步简化:

foo.bak: foo.bar | $(wildcard ~/Dropbox)