Bash

How to sort an array in Bash

27 September 2026 · 8 min read

How to sort an array in Bash

Mastering Bash scripting is a fundamental skill for system administrators, developers, and anyone managing Linux or Unix-like systems. One common task that often arises in shell scripting is the need to organize data, specifically to sort an array in Bash. While Bash itself doesn’t offer a built-in function for array sorting, like many other programming languages, it provides powerful utilities that can be combined to achieve this efficiently. Understanding these methods is crucial for writing robust and effective shell scripts that can process and present information logically. This guide will walk you through various techniques for sorting arrays, whether they contain numbers, strings, or require unique elements, equipping you with the knowledge to tackle complex data manipulation challenges in your Bash scripts.

Understanding Bash Arrays and Their Sorting Nuances

Bash arrays are a powerful feature, allowing you to store multiple values under a single variable name, indexed numerically or associatively. They are incredibly versatile for handling lists of files, configuration parameters, or any collection of related data within your scripts. However, a key distinction of Bash compared to languages like Python or JavaScript is the absence of a direct, single command for array sorting. This means we must leverage external commands, primarily the venerable sort utility, to achieve our desired order.

The flexibility of combining Bash’s array handling with standard Unix tools is a hallmark of shell scripting’s power. Instead of a single “sort()” function, you’ll typically transform your array into a format that sort can understand, process it, and then re-import the sorted data back into a new array. This approach not only allows for sorting but also opens up possibilities for filtering, unique element extraction, and other complex text manipulations through various sort options. Learning this pattern is essential for any serious Bash user looking to manage structured data effectively.

The Canonical Method: Using printf and sort

The most widely accepted and robust method for sorting arrays in Bash involves a combination of printf, sort, and readarray (or mapfile). This technique efficiently converts array elements into a newline-separated list, pipes them to the sort command for processing, and then reads the sorted output back into a new array. This approach is powerful because it externalizes the sorting logic to a highly optimized and feature-rich utility, sort, which can handle various data types and sorting criteria.

For those looking to efficiently sort arrays in Bash, the process involves converting the array elements into a list, piping this list to the sort command, and then re-importing the sorted output. This sequence ensures that the array elements are treated as distinct lines, allowing the sort utility to process them correctly based on its extensive options. This method is not only effective for basic alphabetical or numerical sorting but also forms the foundation for more advanced data organization within your scripts, offering flexibility and control over how your data is ordered.

Let’s break down the steps for this fundamental sorting technique:

  1. Export Array Elements: Use printf "%s\n" "${my_array[@]}" to print each element of the array on a new line. The "%s\n" format string ensures each element is printed as a string followed by a newline, making it suitable for line-oriented tools.
  2. Pipe to sort: Direct the output of printf to the sort command. The sort command, by default, sorts lines alphabetically. You can add options like -n for numeric sort, -r for reverse sort, or -u for unique elements.
  3. Import Sorted Data: Use readarray -t sorted_array (or mapfile -t sorted_array) to read the newline-separated output from sort back into a new array. The -t option removes the trailing newlines from each element, ensuring clean data import.

Consider an example: if you have an array my_numbers=(50 10 30 20 40), you could sort it numerically by running: printf "%s\n" "${my_numbers[@]}" | sort -n | readarray -t sorted_numbers. This command sequence is a cornerstone for robust array manipulation in Bash, allowing for highly customizable sorting logic.

Sorting Numeric Arrays in Bash

When dealing with arrays containing numbers, it’s crucial to instruct the sort command to treat the elements as numerical values rather than strings. By default, sort performs an alphabetical (lexicographical) sort. This means “10” would come before “2” because ‘1’ precedes ‘2’ alphabetically, which is often not the desired behavior for numeric data. To ensure proper numerical ordering, we utilize the -n option with the sort command.

The -n option tells sort to compare according to numerical value. This is indispensable for any script that handles lists of integers, floating-point numbers, or versions. For instance, if you have an array of server response times or file sizes, a numerical sort will provide an accurate, ascending order. Combining this with the printf and readarray method makes sorting numerical data straightforward and reliable, preventing common pitfalls associated with string-based comparisons.

!/bin/bash Example numeric array declare -a unsorted_numbers=(150 20 75 5 100 30) echo "Original numbers: ${unsorted_numbers[@]}" Sort numerically in ascending order printf "%s\n" "${unsorted_numbers[@]}" | sort -n | readarray -t sorted_numbers_asc echo "Sorted numbers (asc): ${sorted_numbers_asc[@]}" Sort numerically in descending order printf "%s\n" "${unsorted_numbers[@]}" | sort -nr | readarray -t sorted_numbers_desc echo "Sorted numbers (desc): ${sorted_numbers_desc[@]}" 

As demonstrated, the inclusion of -n is vital for accurate numerical ordering. For descending order, simply add the -r (reverse) option alongside -n. This method is highly efficient and scalable, making it suitable for arrays of any size, from small lists to large datasets processed within complex shell script array operations.

Sorting Alphabetical and Unique Elements

Sorting arrays containing strings or text follows a similar pattern to numerical sorting, but with a few key differences regarding sort options. By default, without any specific flags like -n, the sort command performs an alphabetical (lexicographical) sort. This is ideal for lists of names, file paths, or any textual data where an A-Z ordering is required. The process remains robust, leveraging the same printf | sort | readarray pipeline.

Beyond simple alphabetical ordering, a common requirement is to extract unique elements from an array while also sorting them. This is where the -u option of the sort command becomes invaluable. When combined with other sorting options, -u ensures that any duplicate lines (which correspond to duplicate array elements) are removed from the output, presenting only distinct, sorted values. This is exceptionally useful for deduplicating lists of users Question & Answer :

I have an array in Bash, for example:

array=(a c b f 3 5) 

I need to sort the array. Not just displaying the content in a sorted way, but to get a new array with the sorted elements. The new sorted array can be a completely new one or the old one.

You don’t really need all that much code:

IFS=$'\n' sorted=($(sort <<<"${array[*]}")) unset IFS 

Supports whitespace in elements (as long as it’s not a newline), and works in Bash 3.x.

e.g.:

$ array=("a c" b f "3 5") $ IFS=$'\n' sorted=($(sort <<<"${array[*]}")); unset IFS $ printf "[%s]\n" "${sorted[@]}" [3 5] [a c] [b] [f] 

Note: @sorontar has pointed out that care is required if elements contain wildcards such as * or ?:

The sorted=($(…)) part is using the “split and glob” operator. You should turn glob off: set -f or set -o noglob or shopt -op noglob or an element of the array like * will be expanded to a list of files.

What’s happening:

The result is a culmination six things that happen in this order:

  1. IFS=$'\n'
  2. "${array[*]}"
  3. <<<
  4. sort
  5. sorted=($(...))
  6. unset IFS

First, the IFS=$'\n'

This is an important part of our operation that affects the outcome of 2 and 5 in the following way:

Given:

  • "${array[*]}" expands to every element delimited by the first character of IFS
  • sorted=() creates elements by splitting on every character of IFS

IFS=$'\n' sets things up so that elements are expanded using a new line as the delimiter, and then later created in a way that each line becomes an element. (i.e. Splitting on a new line.)

Delimiting by a new line is important because that’s how sort operates (sorting per line). Splitting by only a new line is not-as-important, but is needed preserve elements that contain spaces or tabs.

The default value of IFS is a space, a tab, followed by a new line, and would be unfit for our operation.

Next, the sort <<<"${array[*]}" part

<<<, called here strings, takes the expansion of "${array[*]}", as explained above, and feeds it into the standard input of sort.

With our example, sort is fed this following string:

a c b f 3 5 

Since sort sorts, it produces:

3 5 a c b f 

Next, the sorted=($(...)) part

The $(...) part, called command substitution, causes its content (sort <<<"${array[*]}) to run as a normal command, while taking the resulting standard output as the literal that goes where ever $(...) was.

In our example, this produces something similar to simply writing:

sorted=(3 5 a c b f ) 

sorted then becomes an array that’s created by splitting this literal on every new line.

Finally, the unset IFS

This resets the value of IFS to the default value, and is just good practice.

It’s to ensure we don’t cause trouble with anything that relies on IFS later in our script. (Otherwise we’d need to remember that we’ve switched things around–something that might be impractical for complex scripts.)