Files and directories
dirname
Strip the last component from a path, leaving the directory part.
dirname [OPTION...] NAME...
dirname prints a path minus its last component: the directory that contains the file (or
directory) named. Like basename, it is pure string manipulation; nothing is looked up on
disk, so .. and symlinks are left as they are. Use realpath when you need the real,
absolute location.
A path with no slash gives ., the current directory, so the result is always something you
can cd into or prefix to a file name.
Examples
The directory part of a path
dirname /home/dev/demo/data/users.csv
/home/dev/demo/data
The last / and everything after it are removed.
A bare file name
dirname notes.txt
.
There is no directory part, so dirname prints ., which is correct: the file is in the
current directory.
Several paths at once
dirname src/lib/helpers.py logs/app.log /etc
src/lib logs /
GNU dirname accepts any number of names and prints one result per line. The parent of
/etc is /.
Find the directory a script lives in
#!/bin/bash
here=$(dirname "$(realpath "$0")")
echo "script dir: $here"
echo "config: $here/config.ini"
cd /tmp
bash ~/demo/tools/where.sh
script dir: /home/dev/demo/tools config: /home/dev/demo/tools/config.ini
Run from /tmp, the script still finds its own directory. realpath makes $0 absolute
and resolves symlinks first, then dirname drops the script name.
dirname does not resolve .. or symlinks
dirname data/../logs/app.log
dirname link-to-notes
data/../logs .
The result is just the string before the last slash. Use realpath if you need a
canonical path.
The bash equivalent
f=src/lib/helpers.py
echo "${f%/*}"
src/lib
${f%/*} removes the shortest suffix starting with /. Unlike dirname, it returns the
name unchanged when there is no slash, so check for that case.
Common pitfalls
Always quote:
dirname "$path". An unquoted path with spaces becomes several arguments, and GNUdirnamehappily prints a result for each.cd "$(dirname "$0")"uses the path the script was invoked with; if the script was run through a symlink, that is the link's directory. Userealpathfirst if that matters.
GNU vs BSD and macOS
The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).
Older BSD/macOS
dirnameaccepts only one argument; GNU (and recent macOS) accept several.
Options worth knowing
A selection, described in our own words. For the full list, see dirname(1) or dirname --help.
| Option | What it does |
|---|---|
-z, --zero | End each output line with a NUL byte. |
Related
basenameStrip the directory part (and optionally a suffix) from a path, leaving the file name.realpathPrint the absolute, canonical path of a file, with symlinks, . and .. resolved.readlinkPrint where a symbolic link points, or with -f the fully resolved path of any file.pwdPrint the full path of the current working directory.- Parameter expansionThe ${...} operators for defaults, lengths, substrings, trimming prefixes and suffixes, search and replace, and case conversion, without calling sed or cut.
- String manipulationLength, substrings, prefix and suffix removal, search and replace, case, trimming, splitting and joining, done with bash's own expansions instead of external tools.