How to Extract Filename from Absolute Path in Bash

Written by: Aditya Harsh   |   Last updated: May 24, 2023

1. Introduction

Whenever dealing with absolute paths, we will come across situations where we just need the name of the file. What do we do then? Definitely, we can use the available tools in Bash like awk. 

We also have tailor-made tools whose sole purpose is to extract the final component in the file path. Basename is one such command-line utility. Another popular technique is the parameter expansion for removing the directory and trailing suffix from file names. In this tutorial, we will also examine the drawbacks of the different approaches and look at a real-world problem.

2. Why do we need to extract?

The obvious question is why to extract? We have multiple reasons to do so.

  • To rename the file or extension - We may want to extract the filename or extension to rename it with a new name or extension.
  • To have a new file name with the timestamp - We generally have log files in Linux with the same file name and extension. But the file name gets a suffix as the timestamp. 
  • To perform certain actions on the directory like listing all the files in the directory where the given file is present.
  • To use it as an argument or as an input for the script or any Bash command.

3. Extract filename with extension

We will focus on three of the most common ways by which we can extract the filename with its extension in Bash.

3.1 Using basename

With Bash we can employ many utilities to extract the filename and the extension from the given file path. But, why go to such great lengths when we have a tailor-made tool whose sole purpose is to fetch the final component in the file path. Basename is a command-line tool for removing the directory and trailing suffix from file names.

Example:

basename /home/ubuntu/sample.txt
basename /home/ubuntu
The output of 'basename /home/ubuntu/sample.txt' command is 'sample.txt and The output of 'basename /home/ubuntu' command is 'ubuntu'

Basename is a simple tool to implement. All it does is finds the last path separator (/). It displays whatever is present after that. As we can notice, the command is totally unbiased when it comes to files or directories. Its job is to simply give us the information after the final slash.

To make the command interpret more than one path, we supply -a. We can also give the --multiple flag. It is used to achieve the same. Then comes a list of files, each separated by a space. 

Example:

basename -a /home/ubuntu/sample.txt /home/ubuntu/sample1.cfg
The output of 'basename -a /home/ubuntu/sample.txt /home/ubuntu/sample1.cfg' command is sample.txt and sample1.cfg

In our example, we will get the name of the two files with their respective extensions, sample.txt and sample1.cfg from their respective paths. These two will appear in separate lines.

To separate these outputs with NULL rather than a newline we have to pass the -z flag along with it.

Example:

basename -az /home/ubuntu/sample.txt /home/ubuntu/sample1.cfg
describe the basenames of the given paths /home/ubuntu/sample.txt and /home/ubuntu/sample1.cfg respectively using -az option

One major drawback of this command is that it will extract the filename with the extension. We cannot use it just to extract the extension or the directory path.

3.2 Using parameter expansion

Bash has an interesting feature named parameter expansion. With parameter expansions, we can extract parts of a variable. It has a unique syntax. This won't be available with other programming languages.

Example:

filepath=/home/ubuntu/sample.txt
echo ${filepath##*/}
using parameter expansion to extract filename from path

The above example can be generalized as follows:

${variable##pattern}

This trims the longest match from the beginning till the pattern. It displays whatever is after the pattern. The only drawback is that we have to use a variable since this is a parameter expansion. 

In our example, we have used the regex (*) as the pattern. In the pattern we have also added the path separator (/). It will look for all the characters till the last slash (/) and trim it. Hence, we will get the characters after the final path separator. The only drawback here is that we cannot use the string directory. There is no other option but to store the string in a variable.

3.3 Using awk

The awk command was developed by Aho, Weinberger, and Kernighan and gets its name from their initials. It is a powerful, widely used Linux tool that lets us process and manipulate data. It also supports performing arithmetic operations. We can also take its help to extract the filename with its extension.

Example:

filepath=/home/ubuntu/sample.txt
echo $filepath | awk -F/ '{print $NF}'
using awk to extract filename from path

In this example, we have taken a variable to hold the entire file path. We are free to supply that string directly to the echo command. We pipe the result of this echo command so that Bash can send it as an input to the awk command. The -F option available with the awk command acts as the field separator. We have built the regular expression for the awk statement in such a way that the string dissociates into two halves from the final slash (/). $NF ensures that Bash only prints the last column in the record.

4. Example Script

As we have learned different ways of fetching the name of the file, we can look at an example that prompts the user to provide the complete path of the file. The script checks the existence of the file. It then asks the user to provide the directory where he wants to keep a backup of this file with the same name and extension. 

Example:

#!/bin/bash 

read -p "Enter the filename with it's complete path: " fpath


if [ ! -f "$fpath" ]
then
	echo "Invalid file. Please check the input."
else
	read -p "Enter the complete path where you want to copy it: " fdir
	if [ ! -d "$fdir" ]
	then
		echo "Invalid new directory. Please check the input."
else
	fname=`basename $fpath`
		cp $fpath ${fdir}/${fname}
	fi


fi
example script to extract filename from path.

1. The script begins by prompting the user to enter the filename with its complete path. It does it by employing the read command. The user input is stored in the fpath variable.

2. The script verifies the existence of the file specified in fpath using the -f test condition. If the file doesn't exist, it prints "Invalid file. Please check the input."

3. If the file exists, the script again prompts the user to enter the complete path of the destination directory where the file should be copied to. The entered value is stored in the fdir variable.

4. It then checks if the directory specified by fdir does not exist using the -d test condition. If the directory doesn't exist, it prints "Invalid new directory. Please check the input."

5. If both the file and the directory exist, the script uses the basename command to extract the filename from the given file path and stores it in the fname variable.

6. Finally, the cp command is used to copy the file specified by fpath to the destination directory ${fdir}/${fname}.

5. Conclusion

  • We can fetch the file name along with its extension from the absolute file path.
  • Basename is a simple enough command that can be used with certain limitations to pull out the filename.
  • With parameter expansions, we can extract parts of a variable and name of the file
  • We have seen the use of certain readily available powerful tools like awk.

About The Author

Aditya Harsh

Aditya H

Aditya Harsh graduated from BITS Pilani, India with a Bachelor’s in Computer Science in 2015. Since then he has been working as a Software Developer and specializes in automation, especially in Java, and Bash scripting. Over these years, he has worked on a lot of cutting-edge technologies and enjoys using his skills to contribute to technological advances. He believes in the power of knowledge and takes great joy in sharing what he has learned.

SHARE

Comments

Please add comments below to provide the author your ideas, appreciation and feedback.

Leave a Reply

Leave a Comment