There are two commands that can be really helpful when scripting operations that involve filenames and paths. The first of these is dirname: dirname can be used to return the directory portion of a path. The second is basename: basename can be used to output the file name portion of a path.
For our first example, let’s say that we have an output of /var/db/shadow/hash/850F62CD-966C-43A7-9C66-9F9E6799A955, which we know contains the encrypted password for a given user. To just see the UUID here would be done using the following extremely basic incantation of basename:
basename /var/db/shadow/hash/850F62CD-966C-43A7-9C66-9F9E6799A955
Basename can also be used to trim output. For example, let’s say we didn’t need the final portion of the above filename in our output. We could run basename using the -s option, followed by the string at the end that we do not want to see to output of just the first 4 sections:
basename -s -9F9E6799A955 /var/db/shadow/hash/850F62CD-966C-43A7-9C66-9F9E6799A955
The dirname command is even more basic. It outputs the directory portion of the file’s path. For example, based on the same string, the following would tell you what directory the UUID files with the passwords are stored in:
dirname /var/db/shadow/hash/850F62CD-966C-43A7-9C66-9F9E6799A955
A great example of when this gets more useful is keying off of currently active data. For example, if we’re scripting a make operation, we can use the which command to get an output that just contains the path to the make binary:
which make
We can then wrap that for expansion and grab just the place that the active make binary is stored:
dirname `which make`
This allows us to key other operations off the path of an object. A couple of notable example of this is home or homeDirectory paths and then breaking up data coming into a script via a positional parameter (e.g. $1).