Bash Parameter Trimming
Parameter trimming cuts a matching prefix or suffix off a value. One # or % cuts the shortest match, and two cut the longest match.
Shortest and longest prefix
The pattern *. matches up to a dot. One # stops at the first dot, and two ## go to the last dot.
path="archive.tar.gz"
echo "${path#*.}"
echo "${path##*.}"Shortest and longest suffix
The pattern .* matches from a dot to the end. One % stops at the last dot, and two %% go to the first dot.
path="archive.tar.gz"
echo "${path%.*}"
echo "${path%%.*}"Split a file path into parts
The ##*/ form drops the directory part. The %.* form drops the extension, and ##*. keeps only the extension.
file="/home/user/docs/report.txt"
name="${file##*/}"
echo "$name"
echo "${name%.*}"
echo "${name##*.}"Example
file="/data/photos/sunset.jpg"
name="${file##*/}"
base="${name%.*}"
ext="${name##*.}"
echo "File: $name"
echo "Base: $base"
echo "Extension: $ext"Key points
- ${var#prefix}: remove the shortest matching prefix.
- ${var##prefix}: remove the longest matching prefix.
- ${var%suffix}: remove the shortest matching suffix.
- ${var%%suffix}: remove the longest matching suffix.
- Patterns are globs, not fixed text: * matches any characters.
- Trimming builds a new value and never changes the variable.
In this example, the file path holds a directory, a base name, and an extension. The ##*/ form drops everything up to the last slash, leaving sunset.jpg. The %.* form drops the shortest suffix from a dot, leaving sunset. The ##*. form drops the longest prefix up to a dot, leaving jpg.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
For file=archive.tar.gz, what does ${file%%.*} give?