Linux basename Command: Get File Name from Path in Bash

When a script loops over a list of full paths, you usually need only the last part of each one: the file name, often without its extension. The basename command does exactly that. It strips the leading directory path and an optional trailing suffix, then prints what remains.
This guide explains how to use basename on the command line and inside Bash scripts, with practical examples.
Syntax
basename supports two syntax forms:
basename NAME [SUFFIX]
basename OPTION... NAME...The first form takes a single name and an optional suffix to strip. The second form, used with -a, accepts multiple names at once.
Basic Usage
The most common use is to strip the directory path from a full file path:
basename /etc/passwdpasswdbasename also removes any trailing / characters, so both of the following produce the same result:
basename /usr/local/
basename /usr/locallocal
localMultiple Inputs
Use the -a (--multiple) option to process several paths at once, separated by spaces:
basename -a /etc/passwd /etc/shadowpasswd
shadowThis is equivalent to running basename separately on each path and collecting the output.
Remove a Trailing Suffix
Pass the suffix as a second argument to strip it from the result:
basename /etc/sysctl.conf .confsysctlThe same result can be achieved with the -s (--suffix=SUFFIX) option:
basename -s .conf /etc/sysctl.confsysctlBecause -s already implies -a, it is the form to reach for when stripping a suffix from several names at once:
basename -a -s .conf /etc/sysctl.conf /etc/sudo.confsysctl
sudoNUL-Terminated Output
By default, each result ends with a newline. Use the -z (--zero) option to end lines with a NUL character instead of a newline. This is useful when passing output to tools that handle NUL-delimited input, such as xargs -0:
basename -az -s .conf /etc/sysctl.conf /etc/sudo.conf | xargs -0 echosysctl sudoUsing basename in a Bash Script
Inside a script, the usual pattern is to capture the result with command substitution and keep it in a variable:
path="/var/log/nginx/access.log"
file="$(basename "$path")"
echo "$file"access.logKeep "$path" quoted so a path containing spaces remains a single argument. Without those quotes, Bash splits the path into separate operands, so basename may produce the wrong result or exit with an error.
Pass the suffix as a second argument to drop the extension at the same time:
file="$(basename "$path" .log)"
echo "$file"accessOne edge case is worth guarding against. If the name begins with a dash, basename reads it as an option and exits with an error instead of printing anything. Separate the options from the operands with -- whenever the path comes from user input or from another command:
name="$(basename -- "$user_input")"Parameter Expansion Instead of basename
Bash can do the same job on its own, without starting a new process. Parameter expansion
with ##*/ removes everything up to and including the last slash:
path="/var/log/nginx/access.log"
echo "${path##*/}"access.logApplying %.* to that result strips the extension:
file="${path##*/}"
echo "${file%.*}"accessThe two approaches are not quite interchangeable. Every basename call forks a subprocess, so parameter expansion is measurably faster in a loop over thousands of files. On the other hand, basename handles trailing slashes for you: basename /usr/local/ prints local, while ${path##*/} on the same value expands to an empty string.
Rename Files in a Script
The following example shows how to use basename inside a Bash for loop
to rename files
in the current directory, replacing the .jpeg extension with .jpg. It uses mv -n, so an existing .jpg file is not overwritten:
for file in ./*.jpeg; do
[ -e "$file" ] || continue
mv -n -- "$file" "$(basename -- "$file" .jpeg).jpg"
doneStarting the glob with ./ keeps names beginning with a dash from being parsed as options, while the existence check skips the loop when no .jpeg files match.
For bulk file renaming with more advanced pattern matching, the rename command
is often a more concise alternative.
Quick Reference
For a printable quick reference, see the Linux commands cheatsheet .
| Task | Command |
|---|---|
| Strip directory from path | basename /path/to/file |
| Strip directory and suffix | basename /path/to/file.txt .txt |
Strip suffix with -s | basename -s .txt /path/to/file.txt |
| Process multiple paths | basename -a /path/one /path/two |
| Strip suffix from multiple paths | basename -a -s .conf /etc/a.conf /etc/b.conf |
| NUL-terminated output | basename -z /path/to/file |
| Capture in a script variable | file="$(basename "$path")" |
| Strip directory in Bash (no trailing slash) | file="${path##*/}" |
FAQ
What is the difference between basename and dirname?basename prints the last component of a path (the file or directory name), while dirname prints the directory portion. They are complementary tools, but their output may normalize repeated or trailing slashes.
Does basename modify any files?
No. basename only parses the string you pass to it and prints the result. It does not read from or write to the filesystem.
Can basename strip any suffix, not just file extensions?
Yes. The suffix is a plain string match against the end of the name. basename report_final.txt _final.txt produces report. The suffix must appear at the very end of the name to be removed.
How do I strip a file extension in a Bash script without calling basename?
Use parameter expansion: ${filename%.*} removes the shortest trailing suffix matching .*, and ${path##*/} drops the directory part. See Parameter Expansion Instead of basename
for the trade-offs.
Conclusion
The basename command strips the directory path and optional suffix from a file name, which makes it the quickest way to pull a file name out of a full path in a shell script. When the same script runs over very large file lists, reach for ${path##*/} instead and save a subprocess on every iteration.
Tags
Linuxize Weekly Newsletter
A quick weekly roundup of new tutorials, news, and tips.
About the authors

Dejan Panovski
Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 1000+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.
View author page