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*