opscape

Files and directories

dirname

Strip the last component from a path, leaving the directory part.

dirname [OPTION...] NAME...

6 of 6 examples run in Debian 13.7 on 2026-10-31 · coreutils 9.7-3 · manual: dirname(1)

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
explain
output
/home/dev/demo/data

The last / and everything after it are removed.

A bare file name

dirname notes.txt
explain
output
.

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
explain
output
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

tools/where.sh
#!/bin/bash
here=$(dirname "$(realpath "$0")")
echo "script dir: $here"
echo "config: $here/config.ini"
cd /tmp
bash ~/demo/tools/where.sh
output
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
output
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%/*}"
output
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 GNU dirname happily 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. Use realpath first 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 dirname accepts 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.

OptionWhat it does
-z, --zeroEnd each output line with a NUL byte.

Related