A bash function is a way to encapsulate some functionality that you foresee yourself reusing repeatedly. Last week, I wrote about using a bash alias for complex commands, and we saw that functions could be used similarly for commands that require dynamic arguments instead of static ones. But we can use functions for a lot more than just a sophisticated alias. Functions can be used for error handling, and improving script readability and reusability. Here’s a comprehensive guide on how to use functions in bash.
Creating a Bash Function
To create a bash function, we can define it in two ways. For example:
function my_function() {
echo "Hello from the function!"
}
Or we can exclude the “function” keyword and just declare it directly:
my_function() {
echo "Hello from the function!"
}
You can declare these functions in scripts or directly from the bash command line. Here’s an example of the latter in action:
As you can see, to call a bash function, you just need to use the function name, and you’re done! You use the same syntax in scripts as well.
Permanent Bash Functions
If you declare a bash function as shown in the above screenshot, then bash won’t remember it the next time you log in, and you’ll have to declare it all over again. If you want the function declaration to persist, then you’ll need to declare it in the .bashrc file. First you open it in a text editor like this:
vi ~/.bashrc
Then you add it to the file. Here’s an example of my .bashrc file with some alias definitions as well:

Once you’ve added the function definitions to the .bashrc file, you can make them take immediate effect by executing the following command:
source ~/.bashrc
If you define the bash function in a script, you don’t need to do this because bash will find the definition anew whenever you run the script.
Passing Arguments to Bash Functions
One of the benefits of using functions to create aliases instead of the “alias” command, is that you can use dynamic arguments and pass those to the function. For example, take the following function:
greet_last_name() {
echo "Hello, $2!"
}
Unlike in other programming languages, you don’t need to declare the function signature in advance. You can use $1, $2, etc. to refer to the arguments that you pass to the function.
Here’s how the above function works:
In the above screenshot, I’ve used the $2 identifier to extract the last name from the arguments provided to the function. If I had wanted to use the “alias” command instead, I wouldn’t have been able to do this. As proof, here’s what happens when I try and use the “$2” identifier in a regular command:

So the kind of functionality we want is only available in the form of a function.
Returning Values from Bash Functions
Bash functions differ from functions in other languages. We’ve already seen an example of this where it doesn’t require a function signature, but it goes even further than that. Unlike regular functions, a bash function doesn’t return the results of the function. Instead, it returns only whether or not the function was a success or a failure. If success, the return value should be zero (0), and if a failure, then any integer from 0 to 255 will do. It can’t return other data types like strings, for example.
Instead, the standard way for a bash function to supply data is through an “echo” statement. For example:
get_number() {
echo 42
}
In this code, the bash function “echoes” the number 42 and this would “return” the number “42”. Here’s what happens when you try and use the return functionality to return actual data:
get_number() {
return 42
}
result=$(get_number)
echo "Result: $result"
Running the above code, we get this:
As you can see, when I try and return some data and attempt to pass it into a variable, the variable doesn’t contain anything. That’s because bash functions don’t work as functions in the usual sense of the world. The only thing they can “return” is an exit status.
If you want to see the exit status of a bash function, you need to use a special variable called “$?”. This variable contains the exit status of the last successfully executed function. Here’s how to use it:
get_number
echo "$?"
And this is the output:
We need to make sure that we use the “$?” variable as soon as the function executes. If any other command runs in between, the state of the variable will change. If you want to access it later, then I suggest you assign it to another, more permanent variable.
Using “echo” To Return Values
Strangely enough, the correct way to return values from bash functions is the “echo” statement. To those of us with programming experience in other languages, this seems odd. But it’s the best workaround for quick functions. For example:
get_text() {
echo "hello"
}
result=$(get_text)
echo "Result: $result"
As you can see, you can store the “echoed” value in a variable and then use it afterward:
But “echo” is kind of like a “print” command – who would think that printing something can be used as a value? This line of thinking is particularly valid when a function has multiple echo statements. So you have to be careful and use only a single echo statement per function if you want to return a value.
Using Global Variables
A good alternative to using echo for returning values is to store them in a global variable, and then access them from outside the function. Of course, such a process breaks all kinds of best practices in other languages, but functions in bash aren’t meant to be part of a consistent programming language, so this kind of thing is tolerated.
Redirecting Echo Statements to stderr
If you don’t want to mess with global variables in the context of a function, a neat workaround is to redirect the “non-return” values with echo to stderr. Check out my earlier article for a primer on how stderr works. For example:
get_info() {
echo "Fetching user data..." >&2
echo "John Doe"
}
This function has two “echo” statements, but we redirect one of them to stderr.
When we run the function and assign it to a variable, only the echo statement without the redirect is assigned to the variable, so we can print that variable and use it as the return value.
Conclusion
As you can see, bash functions, while looking very similar to existing functions in other languages, are quite different. You don’t define them in the same way with signatures as you do elsewhere, and they don’t return values like normal functions – only status codes, and you have to use a workaround to store their values. However they have several benefits compared to regular aliases, and you can include them in scripts to encapsulate functionality.
As long as you’re cognizant of the ways in which they differ from ordinary functions, you’ll be fine, and it will enrich your Linux experience dramatically once you get used to integrating them in your workflow.

I’m a NameHero team member, and an expert on WordPress and web hosting. I’ve been in this industry since 2008. I’ve also developed apps on Android and have written extensive tutorials on managing Linux servers. You can contact me on my website WP-Tweaks.com!
Leave a Reply