What does % do in Linux shell strings?

When % is used in pattern ${variable%substring} it will return content of variable with the shortest occurance of substring deleted from back of variable.

This function supports wildcard patterns - that's why it accepts star (asterisk) as a substite for zero or more characters.

It should be mentioned that this is Bash specific - other linux shells don't neccessarily contain this function.

If you want to learn more about string manipulation in Bash, i highly suggest reading this page. Among other handy functions it - for example - explains what does %% do :)

Edit: I forgot to mention that when it's used in pattern $((variable%number)) or $((variable1%$variable2)) the % character will function as modulo operator. DavidPostill has more specific documentation links in his answer.

When % is used in different context, it should be recognized as regular character only.


Bash Reference Manual: Shell Parameter Expansion

${parameter%word}
${parameter%%word}

The word is expanded to produce a pattern just as in filename expansion. If the pattern matches a trailing portion of the expanded value of parameter, then the result of the expansion is the value of parameter with the shortest matching pattern (the ‘%’ case) or the longest matching pattern (the ‘%%’ case) deleted. If parameter is ‘@’ or ‘*’, the pattern removal operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is an array variable subscripted with ‘@’ or ‘*’, the pattern removal operation is applied to each member of the array in turn, and the expansion is the resultant list.


By experimenting, I find that a match after % is discarded, when the string is enclosed in curly brackets (braces).

To illustrate:

touch abcd         # Create file abcd

for file in ab*; do
 echo $file        # echoes the filename
 echo $file%       # echoes the filename plus "%"
 echo ${file%}     # echoes the filename
 echo "${file%}"   # echoes the filename
 echo
 echo "${file%c*}" # Discard anything after % matching c*
 echo "${file%*}"  # * is not greedy
 echo ${file%c*}   # Without quotes works too
 echo "${file%c}"  # No match after %, no effect
 echo $file%c*     # Without {} fails
done

Here is the output:

abcd
abcd%
abcd
abcd

ab
abcd
ab
abcd
abcd%c*

Tags:

Linux

Shell

Sh