Given a file path string in Bash, how can I reliably extract the filename and extension, even in cases where the name contains multiple .
s? For example, I would like to extract the name “requirements.updated” and extension “txt” in separate variables from this string:
/home/user/requirements.updated.txt
We can achieve this in Bash using the basename
command and parameter expansion.
First, extract the filename from the path using basename
:
filepath="/home/user/requirements.updated.txt" filename_with_ext=$(basename "$filepath")
Next, use parameter expansion to separate the filename and extension:
filename="${filename_with_ext%.*}" extension="${filename_with_ext##*.}"
In the first line, the ${filename_with_ext%.*}
parameter expansion will remove the shortest match of .*
from the end of $filename_with_ext
, removing only the final .
and text after it.
In the second line, the ${filename##*.}
parameter expansion will remove the longest match of *.
from the beginning of $filename_with_ext
, leaving us with just the text after the final .
.
Our full Bash script will look like this:
#!/bin/bash filepath="/home/user/requirements.updated.txt" filename_with_ext=$(basename "$filepath") filename="${filename_with_ext%.*}" extension="${filename_with_ext##*.}" echo "Path: $filepath" echo "Filename with extension: $filename_with_ext" echo "Filename without extension: $filename" echo "File extension: $extension"
When run, this script will produce the output below:
Path: /home/user/requirements.updated.txt Filename with extension: requirements.updated.txt Filename without extension: requirements.updated File extension: txt
Loved by over 4 million developers and more than 90,000 organizations worldwide, Sentry provides code-level observability to many of the world’s best-known companies like Disney, Peloton, Cloudflare, Eventbrite, Slack, Supercell, and Rockstar Games. Each month we process billions of exceptions from the most popular products on the internet.