Shell – Use shell’s “*” glob, but exclude one file and don’t match directories

makeshellwildcards

I've got a makefile rule that builds a zip/tarbar for distribution. In the recipe, it does some "value added" things, like ensure CR/LF's are correct, and ensures execute bits are correct before packaging.

The project has a buffet of files, but here are the requirements: (1) all files except GNUmakefile need CR/LF, (3) GNUmakefile needs LF only, (3) all files except GNUmakefile needs a-x.

Here's what the recipe looks like:

.PHONY: convert
convert:
    chmod a-x *[^GNUmakefile*] TestData/*.dat TestVectors/*.txt
    unix2dos --keepdate --quiet *[^GNUmakefile*] TestData/*.dat TestVectors/*.txt
    dos2unix --keepdate --quiet GNUmakefile

I'm using * and trying to avoid explicitly listing all the files in the buffet because some are non obvious, like IDE specific files. (*[^<somefile>*] is a neat trick; I got that from Exclude one pattern from glob match).

The problem is I'm matching TestData and TestVectors when performing chmod a-x, so I exclude myself from the directories.

I need to refine things, but I'm not sure how. I want to use the shell's "*" glob, but exclude one file and don't match directories.

How should I proceed?

Best Answer

I'd solve this problem by using GNU Make's filter-out and wildcard functions. The only part of your task that you can't do with them is filter out directories; that has to be done via the shell. Code below is untested and assumes (a) no whitespace or shell metacharacters in any filename, (b) TestData/*.dat and TestVectors/*.txt do not need to be checked for directories.

NORM_TOPLEVEL := $(shell for f in $(filter-out GNUMakefile,$(wildcard *)); \
                   do [ -d "$$f" ] || printf '%s\n' "$$f"; done)
NORM_TESTDIRS := $(wildcard TestData/*.dat) $(wildcard TestVectors/*.txt)

convert:
    chmod a-x $(NORM_TOPLEVEL) $(NORM_TESTDIRS)
    unix2dos --keepdate --quiet $(NORM_TOPLEVEL) $(NORM_TESTDIRS)
    dos2unix --keepdate --quiet GNUmakefile

.PHONY: convert
Related Question