Bash has powerful shell parameter expansion capabilities, which we can use along with a couple of functions to deconstruct filenames.
To get the directory of a file, use dirname
:
me@pc ~/tmp $ dirname /home/steph/tmp/test.txt
/home/steph/tmp
To get the name of a file, use basename
:
me@pc ~/tmp $ basename /home/steph/tmp/test.txt
test.txt
With the use of basename, we can get a file’s root name and extension using Bash parameter expansion. If the file is test.txt
then its root name is test
and its extension is txt
.
${parameter%word}
${parameter%%word}
${parameter#word}
${parameter##word}
If the file is $filename
we have the following:
Expression | Action | Example |
---|---|---|
$(filename%.*} | Get the root name of $filename , taking the last occurence of . as the end of the name, i.e. remove the shortest possible match of .* from the end of $filename . |
test.txt.gz -> test.txt |
$(filename%%.*} | Get the root name of $filename , taking the first occurence of . as the end of the name, i.e. remove the longest possible match of .* from the end of $filename . |
test.txt.gz -> test |
$(filename#*.} | Get the extension of $filename , taking the first occurence of . as the start of the extension, i.e. remove the shortest possible match of *. from the start of $filename . |
test.txt.gz -> .txt.gz |
$(filename##*.} | Get the extension of $filename , taking the last occurence of . as the start of the extension, i.e. remove the longest possible match of *. from the start of $filename . |
test.txt.gz -> .gz |
The following script illustrates the above expansions using a filename provided to the script as an argument $1:
#!/bin/bash
filename=$(basename "$1")
echo
echo Long name, short extension
echo name: "${filename%.*}"
echo extension: "${filename##*.}"
echo
echo Short name, long extension
echo name: "${filename%%.*}"
echo extension: "${filename#*.}"
echo
me@pc ~/tmp $ ./parameter-expansion.sh one
Long name, short extension
name: one
extension: one
Short name, long extension
name: one
extension: one
me@pc ~/tmp $ ./parameter-expansion.sh one.two
Long name, short extension
name: one
extension: two
Short name, long extension
name: one
extension: two
me@pc ~/tmp $ ./parameter-expansion.sh one.two.three
Long name, short extension
name: one.two
extension: three
Short name, long extension
name: one
extension: two.three
References
- Extract filename and extension in bash
- Bash Parameter Expansion
- Section 3.5.3 Shell Parameter Expansion in the Bash manual.