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

发布于 2024-10-30 16:06:21 字数 378 浏览 2 评论 0原文

在我的 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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(16

倾城月光淡如水﹏ 2024-11-06 16:06:22

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

targets: filename1 filename2

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

基本上,您循环遍历目标变量定义的文件名,并使用“test”检查目标是否存在。如果是,则删除该文件,如果不是,则报告该文件不存在。最后一次检查(报告它不存在)是必要的,因为否则如果根本没有目标,则会引发错误

Slightly different from the question, but in case you have a variable containing a list of files which you want to delete you can do

targets: filename1 filename2

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

The basically you loop over the filenames defined by the targets variable and check with 'test' if the target exists. If yes, delete the file, if not, report it is not there. The last check (reporting it is not there) is necessary because otherwise an error is raised in case there is no target at all

我不会写诗 2024-11-06 16:06:22

我想使用上面的命令,但是信誉:)

你可以通过添加 .ONESHELL: 指令在 gnu make 目标中使用多行命令:

all-in-one-shell:
    if [ -a MyApp ] ; then
        echo "here"
    fi

.ONESHELL: all-in-one-shell

这消除了尝试想出创造性的单行或反斜杠的一切。

I wanted to command above, but reputation :)

You can have multi-line commands in gnu make targets by adding the .ONESHELL: directive:

all-in-one-shell:
    if [ -a MyApp ] ; then
        echo "here"
    fi

.ONESHELL: all-in-one-shell

This eliminates trying to come up with creative one-liners or backslash everything.

猥︴琐丶欲为 2024-11-06 16:06:22

我们还可以利用 GNU Coreutils 的 test 内置函数 (手动),这意味着我们可以像这样检查文件是否存在:

check_exist:
    test -f file && echo yes || echo no 

或者更简洁,像这样:

check_exist:
    [ -f file ] && echo yes || echo no 

We can also take advantages from GNU Coreutils's test builtin (manual), which means we can check file existence like this:

check_exist:
    test -f file && echo yes || echo no 

or more neatly, like this:

check_exist:
    [ -f file ] && echo yes || echo no 
巷雨优美回忆 2024-11-06 16:06:21

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

 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

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 

See also:

Update:

I found a way which I really like:

ifneq ("$(wildcard $(PATH_TO_FILE))","")
    FILE_EXISTS = 1
else
    FILE_EXISTS = 0
endif
不弃不离 2024-11-06 16:06:21

第二个最佳答案提到了 ifeq,但是,它没有提到这个 ifeq 在 makefile 中必须与目标名称具有相同的缩进级别,例如仅当当前不存在时才下载文件,可以使用以下代码:

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

# THIS DOES NOT WORK!
download:
    ifeq (,$(wildcard ./glob.c))
        curl … -o glob.c
    endif

The second top answer mentions ifeq, however, it fails to mention that this ifeq must be at the same indentation level in the makefile as the name of the target, e.g., to download a file only if it doesn't currently exist, the following code could be used:

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

# THIS DOES NOT WORK!
download:
    ifeq (,$(wildcard ./glob.c))
        curl … -o glob.c
    endif
记忆で 2024-11-06 16:06:21

问题是当您将命令拆分为多行时。因此,您可以像上面一样在行尾使用 \ 来继续,也可以在 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 了解更多语法。

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.

栀子花开つ 2024-11-06 16:06:21

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

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

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;
       
轻许诺言 2024-11-06 16:06:21

或者只是将它放在一行上,就像 make 喜欢的那样:

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

Or just put it on one line, as make likes it:

if [ -a myApp ]; then rm myApp; fi;
路还长,别太狂 2024-11-06 16:06:21

一行解决方案:

   [ -f ./myfile ] && echo exists

带有错误操作的一行解决方案:

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

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

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

并且 make clean 工作时没有错误消息!

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!

东风软 2024-11-06 16:06:21
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.
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.
怕倦 2024-11-06 16:06:21

缺少分号

if [ -a myApp ];
then
  rm myApp
fi

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

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.

澉约 2024-11-06 16:06:21
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
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
提赋 2024-11-06 16:06:21

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

文件命令的语法是 -

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

删除文件的语法是 -

rm -rf FILENAME

所以现在我们需要一个命令来删除文件(仅当文件存在时),因此我们仅将 OR || 与测试命令一起使用,

test -f FILENAME || rm -rf FILENAME

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

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

Use test command to check if the file exists or not and then use rm to delete it.\

Syntax for the file command is -

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

Syntax for deleting the file is -

rm -rf FILENAME

So now we need a command to delete the file only if it exists so we will only use OR || with the test command

test -f FILENAME || rm -rf FILENAME

use can use multiple commands by using and && within the parenthesis ()

test -f FILENAME || (rm -rf FILENAME && echo "file deleted as it exists")
童话 2024-11-06 16:06:21

答案类似于 @mark-wilkins 的答案,使用 \ 来继续行,并且 ;在 shell 中终止它们或者像 @kenorb 中的那样将其更改为一行都很好,并且可以解决此问题。

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

rm -f myApp

这样更简单、更快、更可靠。只是要小心,不要以斜杠和空变量

rm -f /$(myAppPath) #NEVER DO THIS

你可能最终会删除你的系统。

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.

绝影如岚 2024-11-06 16:06:21
test ! -f README.md || echo 'Support OpenSource!' >> README.md

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

如果您使用 && 而不是 || 那么当文件不存在时会生成错误:

Makefile:42: recipe for target 'dostuff' failed
make: *** [dostuff] Error 1
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
你曾走过我的故事 2024-11-06 16:06:21

我正在尝试:

[ -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 中是否存在文件,这就是答案...

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...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文