What does % do in Linux shell strings?
In Linux shell, what does % do, as in:
for file in *.png.jpg; do
mv "$file" "${file%.png.jpg}.jpg"
done
Solution 1:
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.
Solution 2:
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.
Solution 3:
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*
Solution 4:
In Linux shell (bash
), what does %
do?
for file in *.png.jpg; do
mv "$file" "${file%.png.jpg}.jpg"
done
In this particular case, the %
is pattern matching operator (note it can also be a modulo operator).
Pattern Matching Operator
${var%$Pattern}, ${var%%$Pattern}
${var%$Pattern}
Remove from$var
the shortest part of$Pattern
that matches the back end of$var
.
${var%%$Pattern}
Remove from$var
the longest part of$Pattern
that matches the back end of$var
.Example: Pattern matching in parameter substitution
#!/bin/bash # patt-matching.sh # Pattern matching using the # ## % %% parameter substitution operators. var1=abcd12345abc6789 pattern1=a*c # * (wild card) matches everything between a - c. echo echo "var1 = $var1" # abcd12345abc6789 echo "var1 = ${var1}" # abcd12345abc6789 # (alternate form) echo "Number of characters in ${var1} = ${#var1}" echo echo "pattern1 = $pattern1" # a*c (everything between 'a' and 'c') echo "--------------" echo '${var1#$pattern1} =' "${var1#$pattern1}" # d12345abc6789 # Shortest possible match, strips out first 3 characters abcd12345abc6789 # ^^^^^ |-| echo '${var1##$pattern1} =' "${var1##$pattern1}" # 6789 # Longest possible match, strips out first 12 characters abcd12345abc6789 # ^^^^^ |----------| echo; echo; echo pattern2=b*9 # everything between 'b' and '9' echo "var1 = $var1" # Still abcd12345abc6789 echo echo "pattern2 = $pattern2" echo "--------------" echo '${var1%pattern2} =' "${var1%$pattern2}" # abcd12345a # Shortest possible match, strips out last 6 characters abcd12345abc6789 # ^^^^ |----| echo '${var1%%pattern2} =' "${var1%%$pattern2}" # a # Longest possible match, strips out last 12 characters abcd12345abc6789 # ^^^^ |-------------| # Remember, # and ## work from the left end (beginning) of string, # % and %% work from the right end. echo exit 0
Source Parameter Substitution
Modulo Operator
%
modulo, or mod (returns the remainder of an integer division operation)
bash$ expr 5 % 3 2
5/3 = 1, with remainder 2
Source Operators