In Linux shell, what does % do, as in:
for file in *.png.jpg; do
mv "$file" "${file%.png.jpg}.jpg"
done
In Linux shell, what does % do, as in:
for file in *.png.jpg; do
mv "$file" "${file%.png.jpg}.jpg"
done
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.
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).
${var%$Pattern}, ${var%%$Pattern}
${var%$Pattern}Remove from$varthe shortest part of$Patternthat matches the back end of$var.
${var%%$Pattern}Remove from$varthe longest part of$Patternthat 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, or mod (returns the remainder of an integer division operation)
bash$ expr 5 % 3 25/3 = 1, with remainder 2
Source Operators
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*