Operating System - HP-UX
1828413 Members
3465 Online
109977 Solutions
New Discussion

Scripting Annoyance. Getting the base name from a file name.

 
SOLVED
Go to solution
Steven E. Protter
Exalted Contributor

Scripting Annoyance. Getting the base name from a file name.

This IS a scripting question, not really a Linux question.

This is the name of a Red Hat rpm.
zsh-4.2.0-3.EL.3.i386.rpm

The base Name is everything to the left of the rightmost dash.
zsh-4.2.0 - 3.EL.3.i386.rpm

Sometimes like the one above the base name is two part.

Sometimes the base name is three part.
zsh-html-4.2.0-3.EL.3.i386.rpm
zsh-html-4.2.0 - 3.EL.3.i386.rpm

If I have the full rpm name in a variable, I'm struggling for a reliable way to extract the base name, everything to the left of the right most dash.

TS="zsh-html-4.2.0-3.EL.3.i386.rpm"
echo $TS | awk -F "-" '{print $1 $2 $3 $4 $5 }'

I'm actually opening a sed book thinking this might be the tool of choice.

10 points for a reliable, testable solution.

It will save me a ton of work on a project.

SEP
Steven E Protter
Owner of ISN Corporation
http://isnamerica.com
http://hpuxconsulting.com
Sponsor: http://hpux.ws
Twitter: http://twitter.com/hpuxlinux
Founder http://newdatacloud.com
18 REPLIES 18
Hein van den Heuvel
Honored Contributor
Solution

Re: Scripting Annoyance. Getting the base name from a file name.

Using perl this is trivial:

perl -lne 'print $1 if /(.*)-/' x


With awk, you might glue segments together:

$ awk -F- '{x = $1; i=1; while (++i
Enjoy,
Hein.
Hein van den Heuvel
Honored Contributor

Re: Scripting Annoyance. Getting the base name from a file name.

Another AWK:

$ awk -F- '{print substr($0,1,index($0,$NF)-2)}' x

Look for the star position of the last chunk when split by dashes. Extract up to that point minus 2 for the dash itsef and for being 1 based.

Hein.
Steven E. Protter
Exalted Contributor

Re: Scripting Annoyance. Getting the base name from a file name.

Shalom,

The first perl command, very acceptable for this one time job got me through this issue.

I'm going to use that command to create a data file that will determine the latest, greatest version of each rpm and make a copy of the just that rpm to a new directory.

The point of this endeavor is to allow me to clean up an rpm repository that has multiple versions of many rpms. There is a lot of data space being eliminated.

Consider this thread on hold. People will get something for additional suggestions, but the original problem is solved.

Thanks.

SEP
Steven E Protter
Owner of ISN Corporation
http://isnamerica.com
http://hpuxconsulting.com
Sponsor: http://hpux.ws
Twitter: http://twitter.com/hpuxlinux
Founder http://newdatacloud.com
Hein van den Heuvel
Honored Contributor

Re: Scripting Annoyance. Getting the base name from a file name.

Sorry for the extra replies. 0 points for those.

Why not just use the shell functions

$ x="zsh-html-4.2.0-3.EL.3.i386.rpm"
$ echo ${x%-*}
zsh-html-4.2.0

$ x="zsh-4.2.0-3.EL.3.i386.rpm"
$ echo ${x%-*}
zsh-4.2.0

Hein
Steven E. Protter
Exalted Contributor

Re: Scripting Annoyance. Getting the base name from a file name.

Shalom,

full process:

# cd to rpm directory.

ls -1 | sort -u > file

perl -lne 'print $1 if /(.*)-/' file | sort -u > rpm.base.list


DEST="updates.trimmed/"
while read -r fn
do
nrpmname=$(grep $fn file| tail -n 1)
echo "I am going to copy .... $nrpmname"
TARGET="${DEST}${nrpmname}"
cp -p $nrpmname $TARGET
done < rpm.base.list


Now I'm about to build a patch distribution DVD. Hope it works.

Wish me luck.

No such thing as zero points in an SEP thread unless I think you are fishing. You last post if included in the original would have saved me a few minutes and therefore needs to be part of this post for purposes of documentation.

SEP
Steven E Protter
Owner of ISN Corporation
http://isnamerica.com
http://hpuxconsulting.com
Sponsor: http://hpux.ws
Twitter: http://twitter.com/hpuxlinux
Founder http://newdatacloud.com
H.Merijn Brand (procura
Honored Contributor

Re: Scripting Annoyance. Getting the base name from a file name.

FWIW the basename for this pachage is

zsh-4.2.0-3

*including* the -3
this is the 3rd patch from redhat to zsh version 4.2.0, so maybe perl code like

my ($base, $rest) = split m/\./ => $modname, 2;

is better fitted to your needs

Enjoy, Have FUN! H.Merijn
Enjoy, Have FUN! H.Merijn
Steven E. Protter
Exalted Contributor

Re: Scripting Annoyance. Getting the base name from a file name.

Only one little problem with my process.

One of the results of the loop returned whitespace with the last -n 1.

I need to probably add some grep code to the thing to avoid getting whitesspace or \n results.

Still really hot process. Its gonna save us a lot of GB if I iron it out.

I'm googling for the right grep command.

SEP
Steven E Protter
Owner of ISN Corporation
http://isnamerica.com
http://hpuxconsulting.com
Sponsor: http://hpux.ws
Twitter: http://twitter.com/hpuxlinux
Founder http://newdatacloud.com
Steven E. Protter
Exalted Contributor

Re: Scripting Annoyance. Getting the base name from a file name.

Hmmm

Talking to myself online now. Not good.

grep -v '^$'

Trying that. Going to insert it into the while loop. Blank lines are bad.

Other suggestions welcome.

SEP
Steven E Protter
Owner of ISN Corporation
http://isnamerica.com
http://hpuxconsulting.com
Sponsor: http://hpux.ws
Twitter: http://twitter.com/hpuxlinux
Founder http://newdatacloud.com
James R. Ferguson
Acclaimed Contributor

Re: Scripting Annoyance. Getting the base name from a file name.

Hi SEP:

> One of the results of the loop returned whitespace with the last -n 1. I need to probably add some grep code to the thing to avoid getting whitesspace or \n results.

You can do:

...
nrpmname=$(grep $fn file| tail -n 1)
[ -z "${nrpmname}" ] && continue
...

...which skips the empty element.

Regards!

...JRF...

H.Merijn Brand (procura
Honored Contributor

Re: Scripting Annoyance. Getting the base name from a file name.

Needlessly complicated to do that all in a shell :)

--8<---
#!/usr/bin/perl

use strict;
use warnings;

my $tdir = "updates.trimmed";
mkdir $tdir;
-d $tdir or die "Cannot access $tdir\n";

my $pat = qr{\.}; # Incluse version and patch level
$ $pat = qr{-}; # Only use the base name

my %rpm;
foreach my $rpm (sort glob "*.rpm") {
my ($base, $rest) = split $pat, $rpm, 2;
$base or next;
$rpm{$base} = $rpm; # Keep only the last
}

foreach my $rpm (sort key %rpm) {
my $rpmfile = $rpm{$rpm};
print STDERR "Linking $rpmfile for $rpm\n";
link $rpmfile, "$tdir/$rpmfile";
# Use File::Copy and copy (0 if $tdir is on another FS
}
-->8---

Enjoy, Have FUN! H.Merijn
Enjoy, Have FUN! H.Merijn
Ralph Grothe
Honored Contributor

Re: Scripting Annoyance. Getting the base name from a file name.

All these parsing frolics are quite nice but somewhat redundant I would think.
Have a look at man rpm especially to the --queryformat switch.

Just let rpm sort out what it thinks a package's name is.
(N.B. there are lots of other fields --qf can extract)

e.g.

$ rpm -qp --qf "%{name}\n" nagios-nsca-2.6-1.el4.rf.x86_64.rpm
nagios-nsca

Madness, thy name is system administration
Steven E. Protter
Exalted Contributor

Re: Scripting Annoyance. Getting the base name from a file name.

Shalom,

Problem was not whitespace.

it was an imprecise grep command that got wrong results when looking for one gcc rpm.

change grep $fn to grep ^$fn and problem is solved.

Thanks to all.

This is a really tight script now.

I'm not going to test all options, presented but thank everyone for their fine work.

SEP
Steven E Protter
Owner of ISN Corporation
http://isnamerica.com
http://hpuxconsulting.com
Sponsor: http://hpux.ws
Twitter: http://twitter.com/hpuxlinux
Founder http://newdatacloud.com
James R. Ferguson
Acclaimed Contributor

Re: Scripting Annoyance. Getting the base name from a file name.

Hi (again) SEP:

> change grep $fn to grep ^$fn and problem is solved

...and so a lesson to be remembered by all --- anchors in regular expressions are your friend :-}}

Regards!

...JRF...
H.Merijn Brand (procura
Honored Contributor

Re: Scripting Annoyance. Getting the base name from a file name.

Solved, I know, but to complete the series, combine the best thoughts :)

--8<---
#!/usr/bin/perl

use strict;
use warnings;

use RPM::Header::PurePerl;

my $tdir = "updates.trimmed";
mkdir $tdir;
-d $tdir or die "Cannot access $tdir\n";

my %rpm;
foreach my $rpm (sort glob "*.rpm") {
tie my %hdr, "RPM::Header::PurePerl", $rpm or die "$rpm cannot read header\n";
$rpm{$hdr{NAME}} = $rpm; # Keep only the last
}

foreach my $rpm (sort key %rpm) {
my $rpmfile = $rpm{$rpm};
print STDERR "Linking $rpmfile for $rpm\n";
link $rpmfile, "$tdir/$rpmfile";
# Use File::Copy and copy (0 if $tdir is on another FS
}
-->8---

Enjoy, Have FUN! H.Merijn
Enjoy, Have FUN! H.Merijn
Steven E. Protter
Exalted Contributor

Re: Scripting Annoyance. Getting the base name from a file name.

Ralph,

I don't think rpm can be used to for this process.

The system being used to build and maintain these repositories do not have them all installed.

This is really a cleanup for poor methodology I used in maintaining these repos that wasted a lot of disk space.

Disk space may be cheap but it costs money and people here want to know why I'm using so much.

I also needed to trip the repos down so they'd fit on a single DVD.

Mission accomplished.

I'll give point assignment on later answers some thought. I'll post my final script as well as its been revised further.

SEP
Steven E Protter
Owner of ISN Corporation
http://isnamerica.com
http://hpuxconsulting.com
Sponsor: http://hpux.ws
Twitter: http://twitter.com/hpuxlinux
Founder http://newdatacloud.com
Ralph Grothe
Honored Contributor

Re: Scripting Annoyance. Getting the base name from a file name.

>I don't think rpm can be used to for this process.
>
>The system being used to build and maintain these repositories do not have them all installed.

Note, that I used rpm's -p switch and queried a not installed package itself and not the rpm db.
So there should be no need to have any of the queried rpms installed at all.
You could run this I would think against your yum repo, DVD iso, or whatever.
But I admit, doing one's own clever parsing is more fun and may be more light-weight than using the rpm tool for the purpose.
Madness, thy name is system administration
Steven E. Protter
Exalted Contributor

Re: Scripting Annoyance. Getting the base name from a file name.

I'll give it a try Ralph.

SEP
Steven E Protter
Owner of ISN Corporation
http://isnamerica.com
http://hpuxconsulting.com
Sponsor: http://hpux.ws
Twitter: http://twitter.com/hpuxlinux
Founder http://newdatacloud.com
H.Merijn Brand (procura
Honored Contributor

Re: Scripting Annoyance. Getting the base name from a file name.

FWIW, same for RPM::Header::PurePerl
(no points please)

Enjoy, Have FUN! H.Merijn
Enjoy, Have FUN! H.Merijn