One of the biggest advantages of writing Bash scripts instead of long one-line commands is the ability to organize your code into functions. Functions make scripts easier to read, easier to maintain, and allow you to reuse the same piece of code multiple times without copying and pasting it.
In this post, I'll take a detailed look at one of the most fundamental features of Bash: declaring functions using the name() syntax.
What Is a Bash Function?
A function is simply a named block of commands that can be executed whenever you need it.
Instead of writing the same commands over and over again, you write them once inside a function and call that function whenever necessary.
Think of a function as your own custom Bash command.
For example, instead of repeatedly typing five or six commands every time you want to perform a task, you can simply type:
backup-files
or
show-system-info
provided you've defined those functions.
Function Declaration Syntax
The most common way to declare a function in Bash is:
name () {
commands
}
or, more formally,
name () { commands; } [redirections]
Where:
- name is the name of the function.
- commands are the commands that will be executed when the function is called.
- Optional redirections can be applied to the entire function.
A function does not execute immediately when it is declared. It simply becomes available for later use.
To execute it, simply write its name:
name
Your First Bash Function
Let's start with a very simple example.
#!/bin/bash
files_count() {
ls | wc -l
}
files_count
How This Script Works
Let's break it down step by step.
Step 1 — Define the Function
files_count() {
Here we create a function named files_count.
Nothing happens yet—the function is only being defined.
Step 2 — Execute Commands
Inside the function we have:
ls | wc -l
This command is actually a pipeline made of two separate commands.
The first command:
ls
lists all files and directories in the current directory.
Its output looks something like this:
Documents
Downloads
Pictures
Music
script.sh
Instead of printing this directly to the screen, the pipe operator (|) sends the output to another command.
The second command:
wc -l
counts the number of lines it receives.
If ls produced:
Documents
Downloads
Pictures
Music
script.sh
then wc -l returns:
5
So together,
ls | wc -l
counts the number of files and folders in the current directory.
Step 3 — Call the Function
At the bottom of the script:
files_count
we simply call the function by its name.
The script prints something similar to:
18
depending on how many files and folders exist in the current directory.
Complete Example
#!/bin/bash
files_count() {
ls | wc -l
}
echo "Number of files:"
files_count
Example output:
Number of files:
27
Why Use Functions?
At first glance, this example may seem unnecessary.
Why not simply write
ls | wc -l
directly?
Because real Bash scripts quickly become much larger.
Imagine you need to count files in twenty different places inside a script.
Without functions:
ls | wc -l
...
ls | wc -l
...
ls | wc -l
If you later decide to improve the command, you must edit it everywhere.
With a function:
files_count() {
ls | wc -l
}
you only change the code in one place.
Every call automatically uses the updated version.
Function Names
Function names should be descriptive.
Good examples:
backup_database
cleanup_logs
update_system
create_user
Avoid names like:
test
abc
func1
because they don't describe what the function actually does.
Following a consistent naming convention makes scripts much easier to maintain.
Can Functions Return Values?
In this first example, the function:
- accepts no parameters
- returns no data
- simply executes a command
Although the function produces output on the screen, it is not returning a value in the programming language sense.
Instead, it prints its result to standard output.
We'll cover function parameters, return codes, and capturing output in future articles.
A Better Version
While our original example works, it's worth mentioning that using ls to count files is generally not recommended in production scripts because filenames containing newlines or special characters can produce misleading results.
A more reliable approach would be:
files_count() {
find . -maxdepth 1 | wc -l
}
or
files_count() {
find . -maxdepth 1 -type f | wc -l
}
depending on whether you want to count all directory entries or only regular files.
The original example remains an excellent way to demonstrate how Bash functions work because it's simple and easy to understand.
Best Practices
When writing Bash functions:
- Give functions meaningful names.
- Keep each function focused on a single task.
- Reuse functions instead of duplicating code.
- Add comments for complex logic.
- Prefer readability over clever one-liners.
As your scripts grow from a few lines to hundreds or even thousands, functions become one of the most valuable tools for keeping your code organized.
Conclusion
Functions are one of the core building blocks of Bash scripting. They allow you to group related commands into reusable, easy-to-understand units of code.
The simple name() syntax may look small, but it opens the door to writing clean, modular, and maintainable shell scripts.
In this introductory example, we created a function that counts the number of files in the current directory using a simple command pipeline. While the function itself is straightforward, it demonstrates the fundamental concept you'll use repeatedly in every serious Bash project.
In the next articles of this series, we'll explore how to pass arguments to functions, work with local variables, capture output, and return meaningful status codes, allowing you to build much more powerful and flexible Bash scripts.