What Are Arrays in Fish?
In the Fish shell, arrays are a fundamental data structure for storing ordered collections of values. Fish uses the term lists interchangeably with arrays, but they behave as indexed arrays where each element is a string. An array can hold any number of elements, and each element is accessed via an index starting at 1 (unlike many programming languages that use 0-based indexing).
Arrays are crucial for handling multiple arguments, file names, command outputs, and building complex scripts. Fish provides a rich set of built-in commands and syntax to manipulate arrays with ease.
Why Arrays Matter in Fish Scripting
🚀 Deploy your AI agent in 10 minutes
Managed Hermes hosting. Zero DevOps. 100M tokens/mo included.
Try it free →Understanding arrays unlocks the ability to:
- Process lists of items – e.g., iterating over files, command arguments, or user inputs.
- Store and manipulate command outputs – capturing multiple lines of output into a structured variable.
- Build dynamic commands – constructing argument lists safely with proper quoting.
- Simplify complex logic – using arrays reduces repetitive code and makes scripts more maintainable.
Creating and Initializing Arrays
Fish uses the set command to define and assign values to variables. To create an array, assign multiple values inside parentheses, separated by spaces:
set my_array value1 value2 value3
If you need elements that contain spaces, you must quote them:
set my_array "value with spaces" 'another element' plain
Empty array:
set empty_array
Or using the -l (list) option (explicit):
set -l my_local_array element1 element2
You can also assign the output of a command to an array using command substitution in parentheses:
set files (ls)
This captures each line of ls as a separate array element.
Preserving Newlines in Command Substitution
To preserve literal newlines in the output (treat the whole output as a single element or split by newlines correctly), use the -f or --fields option with set and string split. However, for most cases, (command) splits on newlines. To capture exact lines without trimming, use set lines (cat file | string split \n).
Accessing Array Elements
Fish uses 1-based indexing. To access a specific element:
echo $my_array[1] # first element
To get all elements, simply use $my_array (no brackets). Each element becomes a separate argument:
printf "%s\n" $my_array # prints each element on its own line
To get the length of an array, use count:
count $my_array
Or store the count:
set len (count $my_array)
Slicing Arrays
You can extract a range of elements using the syntax $array[start..end]:
set sublist $my_array[2..4] # elements 2 through 4
Omitting end goes to the last element:
set tail $my_array[3..] # elements from 3 to end
Modifying Arrays
Appending Elements
Use the set -a or set --append flag:
set -a my_array "new element"
Or:
set --append my_array another_item
Prepending Elements
Use set -p or set --prepend:
set -p my_array "first element"
Removing Elements by Index
Use the -e or --erase flag with the variable name and index:
set -e my_array[2] # removes the second element
You can remove a range:
set -e my_array[1..3]
Removing Elements by Value
Fish doesn't have a built-in direct remove-by-value, but you can use set with a filter or string match to create a new array without the unwanted element:
set my_array (string match -v "unwanted" $my_array)
The -v flag inverts the match, returning elements that do not match the pattern.
Replacing Values
Use string replace or a loop. To replace all occurrences of a substring:
set my_array (string replace -a "old" "new" $my_array)
Iterating Over Arrays
Fish's for loop works naturally with arrays:
for item in $my_array
echo "Item: $item"
end
To iterate with an index:
for i in (seq (count $my_array))
echo "Index $i: $my_array[$i]"
end
Or using the index in the loop variable:
set index 1
for item in $my_array
echo "Item $index: $item"
set index (math $index + 1)
end
Associative Arrays / Key-Value Lists
Fish does not have native associative arrays like Bash. However, you can simulate them using two synchronized arrays or a single array with alternating key-value pairs. A common pattern is to store keys and values in separate lists or use the set command to store structured data.
For example, storing key-value pairs in a single list:
set -l config key1 value1 key2 "value with spaces" key3 value3
Then retrieve by searching for the key index and getting the next element. This is cumbersome, so many users leverage fish's ability to define functions with named arguments or use external files. For more complex data, consider using JSON and the jq utility.
Array Best Practices
- Always quote array expansions when you need to preserve elements as they are – In Fish,
$arrayexpands each element as a separate argument, which is usually what you want. If you need to join elements into a single string, use"$array"(which doesn't exist, Fish joins with spaces if used in double quotes? Actually Fish 3.x: when you use$varinside double quotes, it joins array elements with spaces. Soecho "$my_array"prints elements separated by spaces. To preserve original spacing, useprintfor loop. - Use
set -lfor local variables inside functions to avoid polluting global scope. - Prefer
set -aandset -pfor appending/prepending instead of re-assigning the entire array, as it's more efficient and clearer. - Beware of empty array elements – Fish does not have a concept of empty strings in arrays? Actually an element can be an empty string, e.g.,
set arr ''creates an array with one empty element. When expanding, it becomes an empty argument. Use caution with tests like-z. - Use
countto get length instead of relying on$#array(Fish does not support$#for arrays). - Leverage command substitution carefully – By default, command substitution splits on newlines, not spaces. This is safer for filenames with spaces. Use
string splitfor custom splitting. - Document arrays with comments – Explain the structure, especially when simulating multi-dimensional data.
Conclusion
Fish's array handling is intuitive and powerful, with a clean syntax that avoids many pitfalls found in other shells. Mastering arrays enables you to write robust, efficient scripts that can handle complex data flows. Remember the 1-based indexing, the use of set with append/prepend flags, and the seamless integration with loops and command substitution. With practice, arrays will become a natural part of your Fish scripting toolkit.