GNU可以使用空格来处理文件名吗?

qnt*_*ntm 69 shell gnu makefile

我有一个包含多个文件的目录,其中一些文件的名称中有空格:

Test workspace/
Another directory/
file1.ext
file2.ext
demo 2012-03-23.odp
Run Code Online (Sandbox Code Playgroud)

$(wildcard)在这个目录上使用GNU的命令,然后使用遍历结果$(foreach),打印出所有内容.这是代码:

FOO := $(wildcard *)
$(info FOO = $(FOO))
$(foreach PLACE,$(FOO),$(info PLACE = $(PLACE)))
Run Code Online (Sandbox Code Playgroud)

以下是我希望看到的内容:

Test workspace
Another directory
file1.ext
file2.ext
demo 2012-03-23.odp
Run Code Online (Sandbox Code Playgroud)

这是我真正得到的:

Test
workspace
Another
directory
file1.ext
file2.ext
demo
2012-03-23.odp
Run Code Online (Sandbox Code Playgroud)

后者对我来说显然毫无用处.该文档$(wildcard)它返回一个"名字的空格分隔的名单",但完全平整出国家不承认这引起了巨大的问题.也不对文件进行$(foreach).

有可能解决这个问题吗?如果是这样,怎么样?重命名每个文件和目录以删除空格不是一个选项.

Jan*_*dec 49

错误#712表明make不处理带空格的名称.从来没有.

我找到了一篇博文,说它是通过使用\(\\似乎是拼写错误或格式化人工制品)来逃避空间而部分实现的,但是:

  • 除了以外的任何功能都不起作用$(wildcard).
  • 从变量扩展名列表时,包括特殊变量,它不工作$?,$^$+以及任何用户定义的变量.这反过来意味着虽然$(wildcard)匹配正确的文件,但无论如何你都无法解释结果.

因此,使用明确或非常简单的模式规则,您可以使其工作,但除此之外,您运气不好.您将不得不寻找支持空间的其他构建系统.我不确定jam/bjam是否有,scons,waf,ant,nantmsbuild都应该有效.


Pau*_*per 19

GNU Make在空格分隔的文件名中表现很差.

空格在整个单词列表中用作分隔符.

这篇博文很好地总结了这种情况,但是警告:它错误地使用了\\而不是\

target: some\ file some\ other\ file

some\ file some\ other\ file:
    echo done
Run Code Online (Sandbox Code Playgroud)

您也可以使用变量,因此这也可以

VAR := some\ file some\ other\ file

target: $(VAR)

$(VAR):
    echo done
Run Code Online (Sandbox Code Playgroud)

只有该wildcard功能才能识别逃逸,所以你不能做任何花哨的事情.


但是不要忘记你的shell也使用空格作为分隔符.

如果我想更改echo donetouch $@,我必须添加斜杠以逃避它为我的shell.

VAR := some\ file

target: $(VAR)

$(VAR):
    touch $(subst \,\\,$@)
Run Code Online (Sandbox Code Playgroud)

或者,更有可能的是,使用引号

VAR := some\ file some\ other\ file

target: $(VAR)

$(VAR):
    touch '$@'
Run Code Online (Sandbox Code Playgroud)

最后,如果你想避免很多痛苦,无论是在GNU make还是在你的shell中,都不要在文件名中加上空格.如果你这样做,希望Make的有限功能就足够了.

  • “不要在文件名中添加空格”:我从不这样做。但是有时您必须编写一个可以与其他人的源代码一起使用的make文件。 (4认同)
  • 我正在使用 WSL,所以我在 Windows 上拥有所有 linux 工具......并且我所有的二进制文件都在“程序文件”中。大安。 (2认同)

Mr_*_*ags 13

此方法还允许使用列出的文件名,例如作为$?文件列表的用户变量.

在Make中处理空格的最佳方法是用空格替换其他字符.

s+ = $(subst \ ,+,$1)

+s = $(subst +,\ ,$1)

$(call s+,foo bar): $(call s+,bar baz) $(call s+,bar\ baz2)
    # Will also shows list of dependencies with spaces.  
    @echo Making $(call +s,$@) from $(call +s,$?)

$(call s+,bar\ baz):

    @echo Making $(call +s,$@)

$(call s+,bar\ baz2):

    @echo Making $(call +s,$@)
Run Code Online (Sandbox Code Playgroud)

输出

Making bar baz
Making bar baz2
Making foo bar from bar baz bar baz2
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用所有GNU Make函数安全地操作文件名列表.在规则中使用这些名称之前,请务必删除+.

SRCS := a\ b.c c\ d.c e\ f.c

SRCS := $(call s+,$(SRCS))

# Can manipulate list with substituted spaces
OBJS := $(SRCS:.c=.o)

# Rule that has object files as dependencies.
exampleRule:$(call +s,$(OBJS))
    # You can now use the list of OBJS (spaces are converted back).
    @echo Object files: $(call +s,$(OBJS))

a\ b.o:
    # a b.o rule commands go here...
    @echo in rule: a b.o

c\ d.o:

e\ f.o:
Run Code Online (Sandbox Code Playgroud)

输出

in rule: a b.o
Object files: a b.o c d.o e f.o
Run Code Online (Sandbox Code Playgroud)

此信息全部来自其他人发布的博客.

大多数人似乎建议在路径中使用空格或使用Windows 8.3路径,但如果必须使用空格,则转义空格和替换有效.

  • 如果突然有一个带有`+`的文件名怎么办? (2认同)

ben*_*ita 5

如果你愿意更多地依赖你的 shell,这给出了一个可以包含空格的名称的列表:

$(shell find | sed 's: :\\ :g')
Run Code Online (Sandbox Code Playgroud)