Skip to main content
added 1984 characters in body
Source Link
icarus
  • 18.2k
  • 1
  • 39
  • 55

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 $. If your version

Handing the case where there is nothing to "clean"

If the output of find supports itis empty, then after command substitution

rm $(find . -type f -executable)

becomes

rm

and the typical rm command complains that you haven't told it would be betterwhat 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 -delete| xargs rm

Handling arbitrary characters in filenames

as it avoids problems withUnix filenames are made up of components separated by / characters like. The components themselves can be any sequence of characters except / and NUL. In particular a component can include newline characters, spaces in, 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 thema 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 your 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.

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. If your version of find supports it, it would be better to use

clean:
        find . -type f -executable -delete

as it avoids problems with characters like spaces in the output of find if you have them in your filenames.

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.

Source Link
icarus
  • 18.2k
  • 1
  • 39
  • 55

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. If your version of find supports it, it would be better to use

clean:
        find . -type f -executable -delete

as it avoids problems with characters like spaces in the output of find if you have them in your filenames.