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:

  • basename strips 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.

Similar Posts