Refreshed episodes/hosts/comments/series from hpr.sql, and added official HPR transcripts for the 180 episodes aired since the last sync (hpr4516-hpr4695).
132 lines
8.2 KiB
Plaintext
132 lines
8.2 KiB
Plaintext
Episode: 4607
|
|
Title: UNIX Curio #3 - basename and dirname
|
|
Source: https://hub.hackerpublicradio.org/ccdn.php?filename=/eps/hpr4607/hpr4607.mp3
|
|
Transcribed: 2026-07-31 16:15:02 (official HPR transcript)
|
|
|
|
---
|
|
|
|
This is Hacker Public Radio Episode 4607, for 2026-03-31
|
|
Today's show is entitled, "UNIX Curio #3 - basename and dirname"
|
|
The host is Vance and the duration is 00:13:08
|
|
The flag is Clean, and the license is CC-BY-SA
|
|
The summary is "Pulling apart filenames"
|
|
Hi there, I'm Vance and welcome to Unix Curio Number 3.
|
|
This series is dedicated to exploring little known and occasionally useful, trinkets lurking
|
|
in the dusty corners of Unix-like operating systems.
|
|
Hopefully it doesn't seem like I'm picking on Linux Journal, but as with Unix Curio Number
|
|
Number 1 about Shaw, that's Hector Public Radio Episode 4587.
|
|
This entry has been inspired by an article of theirs.
|
|
See the show notes for links to the article and other references.
|
|
The author was demonstrating a clever bash shell script function that would take a file name
|
|
and send the file to standard output, or if the file name ended in .gz, it would decompress
|
|
the file and send the result to standard output.
|
|
This way you could run the function against a set of text files, some of which are compressed
|
|
and some not, and have only text appear on your screen instead of unreadable binary gibberish.
|
|
The way that he accomplished this was to take the value of the first positional parameter
|
|
given to the function, represented by $1.1, remove the extension .gz off the end if present,
|
|
and test whether a file with the resulting name exists.
|
|
If it does, the function would just run cat with the file.
|
|
Otherwise, if the name with .gz at the end exists, it would run g on zip with the height
|
|
and c option to decompress the file and send it to standard output.
|
|
The method chosen to remove the .gz extension was to pipe the name through an appropriate
|
|
pro command.
|
|
This earned the author some criticism on the website and in letters to the magazine for
|
|
cranking up a whole pro interpreter just to chop three characters off the end of a file name.
|
|
Our curio for today is a standard unix utility made for just this purpose called base name.
|
|
Along with its sibling, during name, it is used to pull apart path names to get the
|
|
part that you want.
|
|
What base name does is remove any leading path on the name given to it, and if a suffix
|
|
is specified as well, removes that also.
|
|
If a directory path is given, with or without a trailing slash, it returns the last
|
|
part with no slashes.
|
|
I'll explain with some examples, but they might be a little easier to understand if you
|
|
read the show notes.
|
|
It isn't always clear to listen to commands and code that are read out loud.
|
|
Running base name space slash bin slash gzip would return gzip.
|
|
That's the last part.
|
|
Running base name space slash bin slash gzip space dot SO would also return gzip.
|
|
In this case, since the path name argument that you gave it doesn't end with dot SO,
|
|
the only part that gets removed is the leading path.
|
|
But what if it does?
|
|
Running base name space slash user slash lib slash libz.so, space dot SO would return libz.
|
|
The final part of the path name without the provided extension.
|
|
The suffix can be any text, it doesn't have to be an extension or start with a dot.
|
|
Although that is the way that base name is most often used.
|
|
When you provide a directory name to the command, such as base name space slash user slash lib,
|
|
you would get the last part.
|
|
In this case, just lib with no slashes.
|
|
The counter part, dername does essentially the opposite.
|
|
It removes the last part of the path name and returns a directory name with no trailing
|
|
slash.
|
|
Running dername space slash user slash lib slash lib z dot SO would return slash user slash lib.
|
|
Running dername space slash user slash lib would return slash user.
|
|
Running dername against a name that contains no slashes simply returns a dot representing
|
|
the current working directory.
|
|
I should point out that neither of these utilities cares whether a file or directory with
|
|
the given name actually exists.
|
|
All they do is act on the text string that's been fed to them.
|
|
If you want to use the resulting output in a script, you should take care to use the
|
|
test command with the appropriate option to check that the file or directory exists before
|
|
trying to do something with it.
|
|
To give a historical perspective, base name came first.
|
|
It was present in Bell Laboratory's 7th edition Unix and made its way into the University
|
|
of California's BSD 2.9.
|
|
According to the free BSD manual page, dername did not appear until later in AT&T's system
|
|
3.
|
|
It did not go into the University of California's BSD until version 4.4.
|
|
Standardization of these commands followed a similar pattern.
|
|
Base name first appeared in 1987 in the X-open portability guide which preceded and
|
|
then existed alongside POSIX.
|
|
All it appears that a dername specification didn't emerge until the early 1990s.
|
|
Not all of these standards are freely available online, so it is difficult for me to track
|
|
down exactly when certain things were added.
|
|
However, it is clear that these utilities have been standardized for over 30 years, so it's
|
|
a pretty safe bet that you'll find them both unless you're using a very old Unix-like
|
|
system.
|
|
Getting back to the shell script, we can replace the name editing part by taking the output
|
|
of dername, space, dollar sign 1, follow it with a slash character, then follow that
|
|
with the output of base name, space, dollar sign 1, space.gz.
|
|
It will give us the same result and we can be sure it will work on any Unix-like system,
|
|
no pearl necessary.
|
|
Many of you might be thinking, I could do that with said too, and you're right.
|
|
Basically the command the original script fed to pearl would work exactly the same with
|
|
said, because said is a standard utility, it should already be present on every Unix-like
|
|
system, while pearl might not be.
|
|
One might suspect that as a general purpose text processor said would be slower than base
|
|
name and dername.
|
|
To see how they compared, back when I originally wrote this article in 2010, I ran each
|
|
method 5,000 times with a different randomly generated file name each time.
|
|
It turns out that the critics were right, as the pearl method took the longest time
|
|
to run at 59 seconds.
|
|
Using base name and dername took 44 seconds, a nice improvement, but said blew past that
|
|
at 34 seconds.
|
|
Probably the fact that the script needed to make only one call to said versus two for base
|
|
name and dername made the difference.
|
|
Helpful suggestions in response to the article revealed a shell curio.
|
|
You might have seen the curly brace syntax for parameters.
|
|
For example, say you have a file name in a variable named f.
|
|
To show the file name with a letter x appended, you can't use echo space dollar sign
|
|
fx because that means a variable with the name fx.
|
|
Instead you would put curly braces around the f and follow that with x.
|
|
The shell only interprets what's inside the curly braces as being a variable name.
|
|
Modifiers can also go inside the curly braces and one of these, the percent sign, is just
|
|
what we need to chop off that extension.
|
|
This works in bash, the z shell that's z as in zebra, the corn shell, and any shell
|
|
conforming to the posics standard.
|
|
However, it does not work in the c shell that's c as in Charlie or older implementations
|
|
of the born shell that predate posics.
|
|
We can rewrite the part of the original function that removes the dot gz using dollar sign,
|
|
left curly brace, one percent sign, dot gz, right curly brace, and forego any outside
|
|
utilities.
|
|
Performance.
|
|
After half a second to process those 5,000 file names, not bad at all.
|
|
Thanks for listening and keep an eye out for our next Unix Curio, which will be about
|
|
archiving utilities and formats, here on hiker public radio.
|
|
If you have a question or a suggestion for a future topic, please comment on this episode
|
|
on the hpr website.
|
|
You have been listening to the Hacker Public Radio podcast, at hackerpublicradio.org.
|
|
Today's show was contributed by a HPR listener like yourself.
|
|
If you ever thought of recording a podcast, then visit the HPR site to find out how easy it really is.
|
|
Hosting for HPR has been kindly provided by anhonesthost.com, the Internet Archive, rsync.net, and the HPR Community Content Delivery Network.
|
|
Unless otherwise stated, today's show is released under a Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.
|