Need help with sed statement

Roberto Ragusa mail at robertoragusa.it
Tue May 4 21:08:30 UTC 2010


Patrick O'Callaghan wrote:
> On Tue, 2010-05-04 at 14:11 +0200, Roberto Ragusa wrote:
>> David Bartmess wrote:
>>
>>> I'm trying to express only the filename from a filepath, i.e., 
>>> whoopie.txt from /opt/dev/whoopie.txt.
>> I see you already have received solutions.
>> Here is a simpler one (no sed, no basename):
>>
>> COMPLETEPATH=aa/bb/cc/dd
>> ONLYFILENAME=${COMPLETEPATH##*/}
> 
> Simplicity is in the eye of the beholder. Personally I prefer basename
> (and it's cousin dirname) because I know them and don't have to remember
> the Shell syntax for substitutions.
> 
> How would you adapt your method to do the same as "basename $foo .txt"?
> I don't doubt it can be done, but I can't be bothered working it out.
> That's what simplicity means in my book.

The shell syntax is not as difficult as it looks.
The "#" operator removes a matching part at the beginning (and we are
matching "*/" so anything followed by a slash).
There are two variants: "#" and "##"; the first one tries to match
as few characters as possible; the second one as many as possible.

Same thing with "%" and "%%", but they remove the end of the string.

Some examples:

[rragusa at thinkpad ~]$ x=aa/bb/cc/dd/ee.txt
[rragusa at thinkpad ~]$ echo ${x##*/}            #remove last slash and everything before it
ee.txt
[rragusa at thinkpad ~]$ echo ${x#*/}             #remove first slash and everything before it
bb/cc/dd/ee.txt
[rragusa at thinkpad ~]$ echo ${x%/*}             #remove last slash and everything after it
aa/bb/cc/dd
[rragusa at thinkpad ~]$ echo ${x%%/*}            #remove first slash and everything after it
aa
[rragusa at thinkpad ~]$ echo ${x%.*}             #remove unknown suffix
aa/bb/cc/dd/ee
[rragusa at thinkpad ~]$ file=${x##*/}; nosuff=${file%.txt}; echo $nosuff
                                               #isolate filename and remove known suffix
ee
[rragusa at thinkpad ~]$

The last one achieves (in two steps) what you were asking me.

Simplicity is many things. The syntax is unfamiliar until you learn it,
then it becomes "simple". Your method is easier to learn, but not as robust.
For example, your "basename $foo .txt" will fail if $foo contains a space.
You need quotes around foo to avoid the problem.

[rragusa at thinkpad ~]$ foo="try this.txt"; basename $foo .txt
basename: extra operand `.txt'
Try `basename --help' for more information.
[rragusa at thinkpad ~]$ foo="try this.txt"; basename "$foo" .txt
try this

The shell syntax is immune to the issue because it is an internal
manipulation of a variable, not an external command involving passing
arguments.
That is one manifestation of simplicity, from my point of view. :-)


-- 
   Roberto Ragusa    mail at robertoragusa.it


More information about the users mailing list