Update metadata and transcripts through end of July 2026
Refreshed episodes/hosts/comments/series from hpr.sql, and added official HPR transcripts for the 180 episodes aired since the last sync (hpr4516-hpr4695).
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
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.
|
||||
Reference in New Issue
Block a user