Reputation: 1223
In bash scripting, when t="hello.txt"
both
${t%%.txt}
and ${t%.txt}
returns "hello"
the same goes for ${t##*.}
and ${t#*.}
returns "txt"
.
Is there a difference between them? How do they work?
Upvotes: 2
Views: 5130
Reputation: 8359
In short, %%
removes as much as possible, %
as little as possible.
# t="hello.world.txt"
# echo ${t%.*}
hello.world
# echo ${t%%.*}
hello
From the bash manual:
'${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.
Upvotes: 2
Reputation:
${string%substring}
Deletes shortest match of $substring
from back of $string
.
For example:
# Rename all filenames in $PWD with "TXT" suffix to a "txt" suffix.
# For example, "file1.TXT" becomes "file1.txt" . . .
SUFF=TXT
suff=txt
for i in $(ls *.$SUFF)
do
mv -f $i ${i%.$SUFF}.$suff
# Leave unchanged everything *except* the shortest pattern match
#+ starting from the right-hand-side of the variable $i . . .
done ### This could be condensed into a "one-liner" if desired.
${string%%substring}
Deletes longest match of $substring
from back of $string
.
stringZ=abcABC123ABCabc
# || shortest
# |------------| longest
echo ${stringZ%b*c} # abcABC123ABCa
# Strip out shortest match between 'b' and 'c', from back of $stringZ.
echo ${stringZ%%b*c} # a
# Strip out longest match between 'b' and 'c', from back of $stringZ.
Upvotes: 1