There are several issues.
Passing a $ sign in a Makefile to the shell
You want to run the command
rm $(find . -type f -executable)
to let the shell do the command substitution. To do this you need to write
clean:
rm $$(find . -type f -executable)
with the dollar doubled as Make itself uses $
.
Handing the case where there is nothing to "clean"
If the output of find
is empty, then after command substitution
rm $(find . -type f -executable)
becomes
rm
and the typical rm
command complains that you haven't told it what to remove. One way to address this is to use xargs
to process the output of find
. It takes the output of find
and if there is any it splits it into blocks and runs rm.
clean:
find . -type f -executable | xargs rm
Handling arbitrary characters in filenames
Unix filenames are made up of components separated by /
characters. The components themselves can be any sequence of characters except /
and NUL. In particular a component can include newline characters, spaces, tabs, *
.
For the command substitution case (rm $(find . -type f -executable)
) case the shell will process the output of find. So white-space characters will cause word splitting, *
characters will cause filename "globbing" to take place etc. For reasonable implementations of xargs
this is avoided.
If filenames begin with -
then rm
might consider them to be options to the command. The simple way to avoid this is to add --
to the command to indicate "end of options".
The major remaining issue is newlines. xargs
splits the input on newlines, so if you have a file called abc\ndef
then find
will output
abc
def
and xargs
will invoke rm
with 2 filenamesabc
and def
.
To work around this, tell both find
and xargs
to use the 1 character (NUL) that can't appear in filenames as the deliminator rather than newline.
clean:
find . -type f -executable -print0 | xargs -0 rm --
Best solution, if your find
supports it
clean:
find . -type f -executable -delete
Here you have find directly removing the files, if any. It is more efficient as it doesn't need to start additional processes. There are no shells or xargs processes to need to escape characters. No special characters to tell make
to process. Handles the "no files to delete" case correctly.
find . -type f -executable -delete
? Also note that$
introduces the expansion of a makefile variable.-delete
opt infind
. Do you say that$
has a special meaning inMakefile
and there is no workaround for this?