1. Overview
The dirname command is a convenient utility for handling path strings in Linux. In this quick tutorial, we’ll explore dirname‘s functionality through practical examples.
2. Basic Usage
At its core, dirname extracts the directory component from a given path, effectively isolating the directory portion and excluding the filename. This is helpful when scripting or manipulating file paths programmatically.
The syntax for the dirname command is pretty straightforward:
dirname [OPTIONS] PATH
An example can quickly explain how to use the command and what it returns:
$ dirname /a/nice/dir/file.txt
/a/nice/dir
As we can see, dirname returns the directory component of the path. However, it’s important to note that dirname doesn’t verify whether the input represents a valid path on the filesystem.
For instance, the directory /a/nice/dir doesn’t exist on the system:
$ [[ -d "/a/nice/dir" ]] && echo "Exists." || echo "Directory Not Found."
Directory Not Found.
Next, let’s look at several usage scenarios for this command.
3. Trailing Slashes
We’ve seen that if the input is in the “/dir1/dir2/file” pattern, dirname returns the directory component: “/dir1/dir2”.
However, our input can be a directory. In other words, the input can have a trailing slash. Next, let’s examine how dirname will handle directory input:
$ dirname /a/nice/dir/
/a/nice
As the example above shows, if the input is with a trailing slash, dirname extracts the parent directory of the input directory.
But there is one exception: the root directory “/”. The root directory doesn’t have a parent directory. Therefore, if the input is the root directory “/”, dirname reports “/”:
$ dirname /
/
Additionally, dirname treats consecutive trailing slashes as a single slash:
$ dirname /a/nice//dir//
/a/nice
$ dirname //
/
4. Relative Paths
We know that if a path string begins with ‘/’, it implies an absolute path. Otherwise, it’s a relative path.
Thus far, we’ve only explored how dirname functions with absolute path inputs. Now, let’s examine how it handles various relative path scenarios:
$ dirname a/nice/dir/file.txt
a/nice/dir
$ dirname ./a/nice/dir/file.txt
./a/nice/dir
$ dirname ./
.
$ dirname nice
.
As we can see, even with relative paths, the dirname command accurately identifies and extracts the parent directory component.
However, it’s worth noting that there is a special case:
$ dirname .
.
Passing a dot to dirname, which indicates the current directory, results in a dot.
This is because dirname doesn’t inspect the filesystem. Consequently, it cannot obtain the parent directory of the current directory. Similarly, if inputs beginning with two dots (indicating the parent directory) are passed to dirname, the output will also begin with two dots:
$ dirname ../nice/dir/file.txt
../nice/dir
$ dirname ../../nice/dir/file.txt
../../nice/dir
Again, there is one exception: If we pass “../” to the dirname command, it returns one single dot (the current directory):
$ dirname ../
.
5. Multiple Paths
When multiple paths are provided, dirname processes each one individually, returning the directory component for each.
Next, let’s illustrate this with an example:
$ dirname /a/nice/dir/file.txt relative/dir/subdir/ /another/dir/file
/a/nice/dir
relative/dir
/another/dir
6. The -z Option
By default, the dirname command separates directories in the output with newline characters. However, many Linux filesystems, such as ext4, support special characters, including newline characters:
$ dirname /$'nice\ndir'/file.txt /$'one\ndir'/subDir/file
/nice
dir
/one
dir/subDir
In this example, we passed two path inputs to the dirname command. Both paths contain a newline character. We quoted them using the $’…’ approach. As we can see, dirname reports four lines in the output. This complicates the task of identifying which value corresponds to each input.
To solve this problem, we can use the -z option to tell dirname to delimit output with NULL characters rather than newlines:
$ dirname -z /$'nice\ndir'/file.txt /$'one\ndir'/subDir/file | cat -v
/nice
dir^@/one
dir/subDir^@
It’s worth mentioning that we piped dirname’s output to the **cat* command with the -v option, which prints NULL as ‘*^@’**. Now, we can identify the two directories in the output by taking NULL as the separators.
7. Conclusion
In this article, we’ve explored how to use dirname through practical examples. Armed with this tool in our command-line toolkit, we can confidently and efficiently work with paths.