While putting together a script, I came across this command:
f=${file##*/}
I am curious to know, what does ##
in this line mean?
While putting together a script, I came across this command:
f=${file##*/}
I am curious to know, what does ##
in this line mean?
In bash
, it removes a prefix pattern. Here, it's basically giving you everything after the last path separator /
, by greedily removing the prefix */
, any number of characters followed by /
):
pax> fspec=/path/to/some/file.txt ; echo ${fspec##*/}
file.txt
Greedy in this context means matches as much as possible. There's also a non-greedy variant (matches the smallest possible sequence), and equivalents for suffixes:
pax> echo ${fspec#*/} # non-greedy prefix removal
path/to/some/file.txt
pax> echo ${fspec%%/*} # greedy suffix removal (no output)
pax> echo ${fspec%/*} # non-greedy suffix removal
/path/to/some
The ##*/
and %/*
are roughly equivalent to what you get from basename
and dirname
respectively, but within bash
so you don't have to invoke an external program:
pax> basename ${fspec} ; dirname ${fspec}
file.txt
/path/to/some
For what it's worth, the way I remember the different effects of ##
, %%
, #
, and %
, is as follows. They are "removers" of various types.
Because #
often comes before a number (as in #1
), it removes stuff at the start. Similarly, %
often comes after a number (50%
) so it removes stuff at the end.
Then the only distinction is the greedy/non-greedy aspect. Having more of the character (##
or %%
) obviously means you're greedy, otherwise you'd share them :-)