Extract file basename without path and extension in bash

The basename command has two different invocations; in one, you specify just the path, in which case it gives you the last component, while in the other you also give a suffix that it will remove. So, you can simplify your example code by using the second invocation of basename. Also, be careful to correctly quote things:

fbname=$(basename "$1" .txt)
echo "$fbname"

Here are oneliners:

  1. $(basename "${s%.*}")
  2. $(basename "${s}" ".${s##*.}")

I needed this, the same as asked by bongbang and w4etwetewtwet.


You don't have to call the external basename command. Instead, you could use the following commands:

$ s=/the/path/foo.txt
$ echo "${s##*/}"
foo.txt
$ s=${s##*/}
$ echo "${s%.txt}"
foo
$ echo "${s%.*}"
foo

Note that this solution should work in all recent (post 2004) POSIX compliant shells, (e.g. bash, dash, ksh, etc.).

Source: Shell Command Language 2.6.2 Parameter Expansion

More on bash String Manipulations: http://tldp.org/LDP/LG/issue18/bash.html


A combination of basename and cut works fine, even in case of double ending like .tar.gz:

fbname=$(basename "$fullfile" | cut -d. -f1)

Would be interesting if this solution needs less arithmetic power than Bash Parameter Expansion.