Can GNU create file names with spaces?

I have a directory containing several files, some of which have spaces in the names:

Test workspace/ Another directory/ file1.ext file2.ext demo 2012-03-23.odp 

I use the GNU $(wildcard) command in this directory, and then iterate over the result with $(foreach) , printing everything. Here is the code:

 FOO := $(wildcard *) $(info FOO = $(FOO)) $(foreach PLACE,$(FOO),$(info PLACE = $(PLACE))) 

Here is what I expect to see printed:

 Test workspace Another directory file1.ext file2.ext demo 2012-03-23.odp 

Here is what I actually get:

 Test workspace Another directory file1.ext file2.ext demo 2012-03-23.odp 

The latter is obviously useless to me. the documentation for $(wildcard) flat-out states that it returns a "list of names separated by spaces", but does not fully recognize the huge problems that arise. Also documentation for $(foreach) .

Can I get around this? If so, how? Renaming each file and directory to remove spaces is not an option.

+47
shell gnu makefile
Mar 23 '12 at 11:26
source share
5 answers

Error # 712 suggests that make does not handle names with spaces. Nowhere, never.

I found the message jam / bjam does, scons , waf , ant , nant and msbuild should all work.

+34
Mar 23 2018-12-23T00:
source share

GNU Make does very poorly with names separated by spaces.

Spaces are used as delimiters in the list of words everywhere.

This blog post describes the situation well, but WARNING: it doesnโ€™t use \\ correctly, not \

 target: some\ file some\ other\ file some\ file some\ other\ file: echo done 

You can also use variables, so this will also work

 VAR := some\ file some\ other\ file target: $(VAR) $(VAR): echo done 



Only the wildcard function recognizes shielding, so you cannot do anything without pain.




But don't forget that your shell also uses spaces as delimiters. .

If I wanted to change echo done to touch $@ , I would have to add a slash to avoid it for my shell.

 VAR := some\ file target: $(VAR) $(VAR): touch $(subst \,\\,$@) 

or more likely to use quotation marks

 VAR := some\ file some\ other\ file target: $(VAR) $(VAR): touch '$@' 



After all, if you want to avoid much pain, both in GNU make and in your shell, do not put spaces in the file names. If you do, we hope that the limited features of Make will be sufficient.

+11
May 24 '14 at 21:10
source share

This method will also allow the use of the listed file names, such as $? and user variables, which are file lists.

The best way to handle spaces in Make is to replace spaces for other characters.

 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,$@) 

Outputs

 Making bar baz Making bar baz2 Making foo bar from bar baz bar baz2 

Then you can safely manipulate file name lists using all the GNU Make functions. Just remember to remove + before using these names in the rule.

 SRCS := a\ bc c\ dc e\ fc 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\ bo: # a bo rule commands go here... @echo in rule: a bo c\ do: e\ fo: 

Outputs

 in rule: a bo Object files: a bo c do e fo 

This information is all from the blog that everyone else posted.

Most people seem to recommend using spaces in Windows 8.3 paths or paths, but if you should use spaces, you can use spaces and wildcards.

+9
Feb 01 '15 at 19:17
source share

If you want to rely more on your shell, this gives a list that can contain names with spaces simply:

 $(shell find | sed 's: :\\ :g') 
+2
Dec 22 '16 at 13:42 on
source share

The original question said that โ€œrenaming is not an optionโ€, but many commentators have indicated that renaming is largely the only way that Make can handle spaces. I suggest a middle way: use Make to temporarily rename files and then rename them. This gives you all the power of Make with implicit rules and other kindness, but it doesn't ruin the file name scheme.

 # Make cannot handle spaces in filenames, so temporarily rename them nospaces: rename -v 's/ /%20/g' *\ * # After Make is done, rename files back to having spaces yesspaces: rename -v 's/%20/ /g' *%20* 

You can name these goals manually using make nospaces and make yesspaces , otherwise you may have other goals. For example, you might want to have a โ€œpushโ€ target that allows you to put spaces in file names before synchronizing files with the server:

 # Put spaces back in filenames before uploading push: yesspaces git push 

[Sidenote: I tried the answer, which suggested using +s and s+ , but that made my Makefile harder to read and debug. I gave up on this when he gave me guff about implicit rules: %.wav : %.ogg ; oggdec "$<" %.wav : %.ogg ; oggdec "$<" .]

+1
Aug 6 '17 at 12:05 on
source share



All Articles