Short Tip: Get file extension in Shell script

shell.png
The command basename is often used to extract the real file name without the file type specific file extension:

$ basename thisfile.txt .txt
thisfile

Now sometimes you need it the other way around, you might want to have the file extension. There are of course hundreds of ways to do so, but I found this one appealing since it also shows how the command awk works (which I should learn a bit better I think):

$ echo "thisfile.txt"|awk -F . '{print $NF}'
txt

The “-F” marks the delimiter, “$NF” means the last field generated. Seems to be a pretty straightforward tool.
On a total unrelated note I really like the source code post style of WordPress.

18 thoughts on “Short Tip: Get file extension in Shell script”

  1. Since you are usually operating on variables there are much simpler ways, without calling external tools:

    > F=”thisfile.txt”
    > echo ${F#*.}
    txt
    > echo ${F%.*}
    jaki

  2. Using bash there’s also ${file%.*} to get the filename without the extension and ${file##*.} to get the extension alone. I.e.

    file=”thisfile.txt”
    echo “filename: ${file%.*}”
    echo “extension: ${file##*.}”

    outputs:
    filename: thisfile
    extension: txt

  3. I find the ‘basename’ command invaluable for simple batch renaming tasks such as:
    #br
    for file in *.$1; do
    mv $file `basename $file $1`.$2
    done

    sh$ br htm html

    I miss it the most on windows. Any simpler way to do such batch renames using bash/awk?

  4. sure, there hundred of ways.

    But using awk is just overkill.

    consider:
    # echo foo.bar | cut -d . -f 2

    Unlike the ${}-substitution, this works with non-bash sh-shells, too.

  5. But …
    $ echo “thisfile”|awk -F . ‘{print $NF}’
    returns ‘thisfile’ so use
    $ echo “thisfile.txt”|awk -F . ‘{if (NF>1) {print $NF}}’
    which will return either the extension or null if there isn’t one.

  6. Thanks Tommaso!
    so much better than the gawk method!
    I knew how to do it with gawk but really wanted another way.

  7. … there is also sed for this:

    echo “/real path/.to/file v1.2.3.extension” | sed ‘s/.*\.//’

    Note: this will also work with whitespace and multiple dots in filenames and path (the “cut”-method doesnt provide that feature). This only depends on #!/bin/sh, echo and sed.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.