bash detect file name and extension even there are numerous dots in the name?


New Member

i have found following:

n=${f%.*} # file name without extension
e=${f#*.} # only extension, without dots

f="abc.def.ghi jkl.tar.gz" && echo "${f%.*}_sample.${f#*.}"
result is wrong:
abc.def.ghi jkl.tar_sample.def.ghi jkl.tar.gz

what is good, universal way to get the file name and the extension (tar.gz, tar.xz, tar) even there are dots and spaces in the file name?

GNU bash, version 5.1.0(1)-release


Well-Known Member
That's a tricky one.
If you ensure that you avoid using tons of dots in the filename and only reserve the dots for denoting the file-extension, then what you have will work as expected. But only for files with a single dot extension.
.tar, .txt, .jpg.

But it still wouldn't work for things like .tar.gz, tar.xz etc.

So if you have more than one dot in the name, the simple regex you've used will not work.
If you have multiple dots, you'd probably have to filter the filename and look for specific extensions at the end. (e.g. .tar .tar.gz .tar.xz etc etc.)

So for example, in your script, you could first check to see how many dots are in the filename.
NOTE: Make sure that the path has been stripped out - because it is possible that directory names in the path might also have a dot in them. So you'll need to be dealing exclusively with the filename, NOT the path AND filename!

If there is only a single dot in the filename, then you could use your original code.
If there is more than one dot, you'd need to check the end of the filename against a list of known multi-dot extensions in order to determine where to insert "_sample".

Failing that, you could just check every filename against a list of supported extensions!
$100 Digital Ocean Credit
Get a free VM to test out Linux!

Members online