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.

16 Responses to “Short Tip: Get file extension in Shell script”

  1. mikmach Says:

    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. liquidat Says:

    Nice one as well, didn’t know that. But as I said there are hundreds of ways I think.

  3. Mellen Says:

    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

  4. Mellen Says:

    Well… almost what mikmach says… :)

  5. Thiago Macieira Says:

    The source code paste looks horrible in akregator: newlines are missing.

  6. liquidat Says:

    Thiago, I wonder if that is a bug in Akregator or in the source code thing…

  7. tabrez Says:

    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?

  8. gsauthof Says:

    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.

  9. Alan Says:

    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.

  10. Tommaso Says:

    another bash shortcut:
    $ a = textfile.test.txt
    $ echo ${a/*./}
    txt

  11. liquidat Says:

    I never realized that there are so many ways to do that :D

  12. lumak Says:

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

  13. anonymous Says:

    … 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.

  14. anonymous Says:

    replace single and double quotes with the corect ones if you c&p this…

  15. extensie isoleren | hilpers Says:

    [...] naam=’bestand.ext’ > echo ${naam#*.} Ah, net teruggevonden, bovenstaande en nog veel meer: http://liquidat.wordpress.com/2007/0…-shell-script/ Richard Rasker — [...]


Comments are closed.