Extract Extension Name from Filename in Bash Shell

The following commands will extract the file extension string from a given filename. The only trick to these commands is they will give you the final extension after the last ‘.’. In other words, they will not work for extensionless files and files with two dot extension names (like file.tar.gz or similar).

for i in *; do echo $i | sed -e 's/.*[.]\(.*\)/\1/'; done
for i in *; do echo $i | awk -F. '{ print $NF }'; done

This command will grab the first dot extension even if there are two (it will return tar for file.tar.gz).

for i in *; do echo $i | cut -d'.' -f2; done

I’d love to hear your suggestions in the comments if you have a better, more optimized way of doing this.

Feel free to donate if this post prevented any headaches! Another way to show your appreciation is to take a gander at these relative ads that you may be interested in:

There's 4 Comments So Far

  • tasidus
    March 2nd, 2012 at 10:14 am

    How about:
    for i in *; do echo ${i##*.}; done

    see here for how this works: http://tldp.org/LDP/abs/html/string-manipulation.html

  • [email protected]
    March 2nd, 2012 at 10:51 am

    Thanks for that! Always good to know there’s more than one way to skin a cat! 🙂

  • [email protected]
    March 4th, 2012 at 10:14 pm

    This came via email from a subscriber, Jim. Thanks Jim!

    Hi Derek,

    You could use

    sed -e ‘s/.*\.//’

    instead of

    sed -e ‘s/.*[.]\(.*\)/\1/’

    which is a bit simpler. It works because the sed regular expression handler
    is “greedy” – it matches everything upto the last possible ‘.’ It gives the
    same results as yours.

    Using sed for the second case, you could use

    sed -e ‘s/[^.]*\.//’

    This says match any number of chars that are not (^) ‘.’ and a ‘.’
    and replace with nothing. It works very like the the last dot example.
    a.b -> b a -> a a.b.c -> b.c etc

    I’m sure you can do this using some of the bash variable operators, but
    then any scripts would be restricted to bash, and not dash or other more
    basic ones.

    I love using ‘cut’ for these sorts of things, but don’t think it can be
    made to work to give the last ‘.’ field, when there are several. By the
    way, The cut example for all the extensions could be

    cut -d. -f2-

    which will give all the extensions e.g. file.tar.gz -> tar.gz

    all the best

  • pibarnas
    April 21st, 2012 at 12:16 am

    I think, Jim, if the goal is to extract only the extension, the correct would be sed -e ‘s/\..*//’, or substitute everything after a dot (scaped) with nothing, isn’t it?

Share your thoughts, leave a comment!