Kusalananda
Kusalananda

Reputation: 15633

GNU Make: Remove all parts of filename after first dot

In a GNU Makefile (on an Ubuntu Linux system), how may I remove the filename suffix of each filename in a list in such a way that the filenames are truncated at the first dot?

Suppose I have

NAMES = file1.a.b.c file2.x.y.z file3.b file4.foo

where the names may come from a filename globbing expansion using $(wildcard file*).

I would like to end up with

NEWNAMES = file1 file2 file3 file4

or possibly even

NEWNAMES = file1.quux file2.quux file3.quux file4.quux

(not necessarily in this order)

The $(basename ...) function only strips the last suffix from the names.

In a shell supporting arrays, I would have used something like "${names[@]%%.*}" or "${names[@]/%.*/.quux}".


The reason for wanting to do this is that we're working with a bioinformatics environment where files have a known filename prefix, but their suffix may be any combination of .fa, .fas, .fasta (etc.), with the possibility of these suffixes doubling up (as in .fa.fa) and also having a file compressor suffix, such as .gz, at the end.

We would like to transform the filenames into normalised prefix.suffix filenames in the Makefile, regardless of how complex the initial filename suffix was.

Upvotes: 2

Views: 955

Answers (3)

Vroomfondel
Vroomfondel

Reputation: 2898

If you want a more flexible approach, you can use gmtt, a GNUmake library:

include gmtt-master/gmtt-master/gmtt.mk

NAMES = file1.a.b.c file2.x.y.z file3.b file4.foo

$(info $(foreach fn,$(NAMES),$(call glob-match,$(fn),*.*)$(newline)))

NEWNAMES = file1.middle.quux file2.middle.quux file3.middle.quux file4.more.middle.quux

$(info $(foreach fn,$(NEWNAMES),$(call glob-match,$(fn),*.*.quux)$(newline)))

Output:

  $ make
 file1 . a.b.c
  file2 . x.y.z
  file3 . b
  file4 . foo

 file1 . middle .quux
  file2 . middle .quux
  file3 . middle .quux
  file4 . more.middle .quux

make: *** Keine Ziele.  Schluss.

The glob-matcher returns a list of separated strings which you can process further.

Upvotes: 1

MadScientist
MadScientist

Reputation: 100946

If you want to do it with make functions without using a shell, you can use something like this:

NAMES := $(foreach F,$(wildcard file*),$(firstword $(subst ., ,$F)))

Upvotes: 3

Pontus
Pontus

Reputation: 36

I'm not sure what platforms are targeted here (do we have a SUSv3 compliant /bin/sh) as well as any requirements on the names.

If it's acceptable that names can't contain whitespace, I think a simple

NEWNAMES = $(shell for p in $(NAMES); do echo $${p%%.*};done) 

comes close enough and is easy to understand.

Upvotes: 1

Related Questions