As a Linux system administrator or developer, you often need to work with files and directories. Sometimes you only need the filename without the extension to perform certain operations like renaming files or converting file types. Bash provides easy ways to extract the basename from a full filepath without the extension. In this comprehensive guide, we will explore the common techniques to read filenames without extensions in Bash.
Why Read Filenames Without Extensions?
Here are some common use cases where you need the filename without the extension:
- Rename files by removing extensions
- Convert files from one format to another (e.g. .txt to .docx)
- Pass basenames to other commands and scripts
- Print/display filenames without cluttering the output
- Match and process files based on names only
- Read user-friendly filenames rather than full paths
As you can see, stripping the extensions helps clean up filenames and paths for easier processing and scripting.
Using the basename Command
The basename command in Bash extracts the base from a full filepath. It can also remove suffixes/extensions in one go.
Here is the syntax:
basename [options] [filepath] [suffix]
Let‘s see some examples to understand how to use basename:
Print Basename with Extension
Pass a full filepath to get just the filename with extension printed:
$ basename /home/user/docs/report.txt
report.txt
Remove Extension
To remove the extension, pass it as the suffix parameter:
$ basename /home/user/docs/report.txt .txt
report
Multiple Filepaths
Use the -a option to strip basename from multiple files:
$ basename -a /home/user/docs/report.txt /usr/local/log.csv
report.txt
log.csv
Custom Separator
The -z option replaces newlines with a custom separator (NUL byte by default):
$ basename -az /home/user/docs/*.txt /usr/local/*.csv
report.txtNULlog.csv
As you can see, basename lets you easily extract basenames and remove extensions in just one step.
Parameter Expansion in Bash
In addition to basename, you can also use parameter expansions in Bash to manipulate filenames and paths.
Here is the standard syntax for parameter expansion:
${parameter%pattern}
${parameter%%pattern}
${parameter#pattern}
${parameter##pattern}
This allows you to expand variables and slice off either prefixes or suffixes from the paramter value based on a glob pattern.
Let‘s see some examples of using parameter expansions for filenames and paths:
Strip Extension
To remove the extension regardless of length:
filename=/home/user/docs/report.txt
basename=${filename%.*}
echo $basename
/home/user/docs/report
The %.* pattern removes the shortest matching dot suffix which represents the file extension typically.
If you have multiple dots, you can remove everything after the first dot only:
file=/path/to/image.png.bak
name=${file%.png*}
echo $name
/path/to/image
Extract Basename Only
To just get the basename without directories:
filepath=/home/user/docs/report.log
basename=${filepath##*/}
echo $basename
report.log
The ##*/ pattern strips the longest prefix matching the */ glob which matches directories in filepaths.
Change Extension
You can combine basename extraction and append a new extension:
file=/home/user/docs/report.txt
converted=${file%.*}.docx
echo $converted
/home/user/docs/report.docx
As you can see, parameter expansion gives you a lot of flexibility for string manipulation without calling external programs.
Function to Get Basenames
For reusable code, you can also wrap basename extraction logic into a Bash function:
function basename {
filename="$1"
basename=${filename##*/}
basename=${basename%.*}
echo "$basename"
}
basename /home/user/docs/report.txt
# Prints report
Some key advantages of using functions:
- Encapsulates logic in one place
- Easy to reuse across multiple scripts
- Allows additional processing if needed
- Avoids repetitive code
The above is just a simple example. You can build more versatile functions to suit your specific requirements.
Practical Examples
Now let‘s go over some practical examples of how stripping file extensions helps simplify filename processing.
Process Files by Name Pattern
This script extracts basenames and then runs commands only on .txt and .csv files:
#!/bin/bash
for file in *.*
do
name="${file%.*}"
# Check file type
if [[ "$name" == *.txt || "$name" == *.csv ]]
then
process "$file"
fi
done
Rename Files by Removing Extension
This loop renames all files by removing any extensions:
#!/bin/bash
for file in *.*
do
name="${file%.*}"
mv "$file" "$name"
done
Convert File Types
Similarly, you can convert between file formats by changing extensions:
#!/bin/bash
for file in *.txt
do
newfile=${file%.*}.docx
# Convert txt to docx
convert $file $newfile
rm $file
done
The script iterates over .txt files, changes the extension to .docx and then converts contents to docx Word format.
As you can see, stripping file extensions helps simplify batch file operations.
Conclusion
While filenames contain useful information for humans, extensions and long paths can clutter scripts and outputs.
Bash gives simple ways to extract just the filename minus the extensions for cleaner processing:
basenamestrips paths and removes suffixes- Parameter expansions flexibly slice parts of variables
- Functions allow reusable logic for basenames
So next time you just need to work with the user-friendly basename, use one of these approaches. Your Bash scripts will be cleaner and easier to manage file operations.


