18

I have a makefile that I use to compress pictures:

src=$(wildcard Photos/*.jpg) $(wildcard Photos/*.JPG)
out=$(subst Photos,Compressed,$(src))

all : $(out)

clean:
    @rmdir -r Compressed

Compressed:
    @mkdir Compressed

Compressed/%.jpg: Photos/%.jpg Compressed
    @echo "Compressing $<"
    @convert "$<" -scale 20% "$@"

Compressed/%.JPG: Photos/%.JPG Compressed
    @echo "Compressing $<"
    @convert "$<" -scale 20% "$@"

However, when I have a picture with a space in its name, for example Piper PA-28-236 Dakota.JPG, I get this error:

make: *** No rule to make target `Compressed/Piper', needed by `all'.  Stop.

I think this is a problem in the wildcard command, but I'm not sure what to change to get it to work.

How can I modify my makefile to allow for spaces in file names?

iBelieve
  • 1,502
  • 17
  • 32

1 Answers1

12

Generally having spaces in file names is a bad idea with make, but for your case this may work:

src=$(shell find Photos/ -iname '*.JPG' | sed 's/ /\\ /g')

out=$(subst Photos,Compressed,$(src))

all : $(out)

Compressed:
  @mkdir Compressed

Compressed/%: Photos/% Compressed
  @echo "Compressing $<"
  @convert "$<" -scale 20% "$@"
perreal
  • 94,503
  • 21
  • 155
  • 181
  • Thanks for your help, that works to fix the spaces in the wildcard problem. I modified it to `src=$(shell ls Photos | sed 's/ /\\ /g;s/.*/Photos\/\0/')` to allow `JPG` and `jpg`. However, now I'm getting the error `make: *** No rule to make target 'Compressed/Piper PA-28-236 Dakota.JPG', needed by 'all'. Stop.` So now I need to figure out how to get targets with spaces to work. – iBelieve Dec 20 '12 at 01:48
  • 1
    I got it to work, thanks for all your help. Replacing with a `?` fixes the targets issue, but added a `?` in the resulting file. I ended up using a call function: `replace = echo $(1) | sed 's/?/ /g'` and then used it with this command: `@convert "$<" -scale 20% "\`$(call replace,$@)\`"` – iBelieve Dec 20 '12 at 02:10
  • Should I accept your answer or should I create my own answer detailing all I did to get it to work, showing the final Makefile? – iBelieve Dec 20 '12 at 02:13
  • Hmmm, when I add a new image to the `Photos` directory or delete one of the compressed images from the `Compressed` directory, the Makefile compresses ALL the pictures, not just the new one or the one with out a compressed version. – iBelieve Dec 20 '12 at 02:34
  • Thanks for the updated answer, it is much simpler. However, the problem I described in my last comment still happens. – iBelieve Dec 22 '12 at 18:24
  • @iBelieve, if you make twice in a row, without adding or removing any photos, does it compress and recompress all pictures? Or all space-named pictures? Perhaps GNU Make is using the space-unsafe variables $^ and $? internally to keep tabs on which prerequisites are new, failing, and assuming that all prerequisites are new. That's a bug in GNU Make that can be fixed in a backwards-compatible manner. – Bjartur Thorlacius Apr 05 '20 at 10:51
  • Never mind, I tested a similar setup but named the targets without spaces in filenames even though the prerequisite filenames contained spaces, and GNU Make 4.3 did not rebuild when unnecessary. – Bjartur Thorlacius Apr 05 '20 at 11:11