for i in *.shp; do ; mv -v "${i}" "${i%.*}_MYSUFFIX.${i##*.}" ; done

This loop inserts_MYSUFFIX before file extension in my directory...great stuff but I am struggling to understand the details of this bit does:


Character expansion / substitution ??? I don't know where to begin looking for an explanation and documentation to learn this ?


3 Answers 3


Assuming that i contains testing.an.string.with.dots.shp, just add some spaces to the part that you don't understand and look at the result:

$ echo "${i%.*}   _MYSUFFIX.    ${i##*.}"
testing.an.string.with.dots   _MYSUFFIX.    shp

So, those "parameter expansions" could be found in the bash manual with:

LESS=+/#word man bash

That link goes to the "Remove matching prefix pattern" entry and the following entry is the "Remove matching suffix pattern". The names hint at what each does. One removes characters from the front of a variable (parameter) content, the other from the end (tail).

A single character # or % removes the shorter matching section.

A double character ## or %% removes the longest matching section.

So, a "${i%.*}" will reproduce the content of $i removing the shortest string from the end that starts with a dot (.) up to the end. That simply means: "remove the extension (and dot)".

A "${i##*.}" will reproduce the value of $i while removing the longest string from the front that match anything followed by a dot. That may be simplified in words to say: only retain the extension.

Then, all three parts are concatenated in one single string.


So tl;dr from that manual:

nameFront="${i%.*}" # Deletes shortest match of ".*" from back of $i, one "." only
echo Front=$nameFront
nameExt=${i##*.}    # Deletes longest match of "*." from front of $i, so include "."'s
echo Ext=$nameExt
echo New="${nameFront}_MYSUFFIX.${nameExt}"


It is called "string manipulation in bash"

Here is a very good text book on it:

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .