I'd like to extract the extension out of a filename with multiple dots. For instance:


I should get "tar.gz", not "gz" or "0.tar.gz".

I prefer a solution not relying on bash exclusive features (using posix commands like sed or cut is ok).

EDIT: A reasonable solution could be: "get everything after the second-last dot, but exclude numbers or substrings with a lenght <=1"

  • 1
    Determining an extension is hard. Either make a list of acceptable extensions, or pick a range of acceptable number of dots. – muru Jan 27 '15 at 19:40
  • And I suppose you have never encountered files from a simple splitting (...0, ...1, etc.)? – muru Jan 27 '15 at 21:00
  • ok, there are common single-letter file extensions like .h, .a, etc., but in this case they won't occur. – eadmaster Jan 27 '15 at 21:33
  • oh, sorry that i missed this answer. It fits perfectly my case. – eadmaster Jan 27 '15 at 23:29

Assuming that an extension starts with a letter after the period, the following command prints .tar.gz:

echo gbamidi-v1.0.tar.gz | awk \
    'BEGIN { FS = "\." } \
    { \
        extension = ""; \
        i = NF; \
        while ((i > 1) && (substr($i, 1, 1) ~ /[A-Za-z]/)) { \
            extension = "." $i extension; \
            i-- \
        }; \
        print extension \
  • In zsh I'd do this: var=`echo version12.0.foo.tar.gz | sed 's,[[:digit:]]\+.[[:digit:]]\+,,'` ; echo ${var#*.} just strip out any decimal numbers, assign the results to variable 'var' then strip out anything up to and including the first dot from 'var'. – Ray Andrews Jan 28 '15 at 0:56

This may not be valid in all cases, but .gz is the extension. foo.tar.gz first has to be extracted to a foo.tar, then unarchived. The fact you can do that in one command is just convenience.

You need to get the extension? It's .gz.

If you need something else then you're going to need to target specific things using regex, awk, cut or the like.

Not the answer you're looking for? Browse other questions tagged or ask your own question.