This post was originally published on go2linux.org on February 24, 2008. The domain is no longer mine, but I am the original author. I am republishing it here on garron.me with corrections and improvements.

Introduction

basename strips the directory path from a file name, and optionally removes a trailing suffix. It is part of GNU Coreutils and is available on every Linux system.

It is most useful inside shell scripts where you need only the file name from a full path.

Syntax

basename NAME [SUFFIX]
basename OPTION... NAME...

Basic examples

Strip the directory from a path:

basename /usr/bin/sort

Output: sort

Strip both the directory and a suffix:

basename include/stdio.h .h

Output: stdio

Strip a .tar.gz extension:

basename /home/ggarron/backups/archive.tar.gz .tar.gz

Output: archive

Multiple names at once

With the -a flag, you can pass multiple names:

basename -a /usr/bin/sort /usr/bin/ls /usr/bin/cat

Output:

sort
ls
cat

Use a custom suffix separator

With -s, you specify a suffix and can pass multiple names:

basename -s .txt /home/user/doc1.txt /home/user/doc2.txt

Output:

doc1
doc2

In shell scripts

basename is most commonly used in scripts to extract the file name from $0 (the script's path) or from a loop variable.

Get the script's own name for error messages:

#!/bin/bash
SCRIPTNAME=$(basename "$0")
echo "$SCRIPTNAME: error: something went wrong" >&2

Rename files by stripping a suffix and adding a new one:

for f in /var/log/*.log; do
    name=$(basename "$f" .log)
    cp "$f" "/tmp/${name}.bak"
done

Process files in a loop without the directory prefix:

for f in /etc/cron.d/*; do
    echo "Cron job: $(basename "$f")"
done

dirname — the complement to basename

dirname does the opposite: it strips the file name and returns the directory.

dirname /usr/bin/sort

Output: /usr/bin

Together they let you split a path into its two components:

path=/etc/apt/sources.list
dir=$(dirname "$path")     # /etc/apt
file=$(basename "$path")   # sources.list

Always quote your variables

When file names may contain spaces, quote the argument to avoid word splitting:

basename "$f"        # correct
basename $f          # breaks on spaces

See also

  • dirname — return the directory portion of a path
  • readlink -f — resolve a path to its absolute form
  • realpath — similar to readlink -f, available on modern systems