Short Tip: Get file extension in Shell script

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

$ basename thisfile.txt .txt

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}'

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#*.}
    > echo ${F%.*}

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

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

    filename: thisfile
    extension: txt

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

    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.

    # echo | 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 Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

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