How do I translate this `for` loop for the fish shell?
for
loop for the fish shell? with practical examples, diagrams, and best practices. Covers fish development techniques with visual explanations.Categories:
Translating Bash/Zsh 'for' Loops to Fish Shell Syntax

Learn how to convert traditional shell 'for' loops into idiomatic Fish Shell syntax, covering common patterns like iterating over ranges, arrays, and command output.
The Fish Shell (Friendly Interactive SHell) offers a more user-friendly and powerful command-line experience compared to traditional shells like Bash or Zsh. While its syntax is often simpler and more intuitive, it can differ significantly, especially for scripting constructs like for
loops. This article will guide you through translating common for
loop patterns from Bash/Zsh to Fish Shell, ensuring your scripts run smoothly in your preferred shell.
Understanding Fish Shell's Loop Philosophy
Fish Shell's design prioritizes clarity and consistency. Unlike Bash/Zsh, which often requires specific syntax for array expansion or command substitution within loops, Fish aims for a more natural expression. Variables in Fish are always arrays, even if they contain a single element, simplifying iteration. The for
loop syntax is generally more straightforward, often eliminating the need for do
and done
keywords or explicit seq
commands.
flowchart TD A[Start with Bash/Zsh Loop] --> B{Identify Loop Type} B -->|Numeric Range| C[Use 'for i in (seq ...)' or 'for i in (math ...)'] B -->|Array/List| D[Use 'for item in $array_var'] B -->|Command Output| E[Use 'for line in (command)'] C --> F[Implement Fish Syntax] D --> F E --> F F --> G[Test and Refine] G --> H[End]
Decision flow for translating Bash/Zsh loops to Fish Shell
Translating Common Loop Patterns
Let's look at some common for
loop scenarios and how they translate from Bash/Zsh to Fish Shell.
set my_var 1 2 3
, $my_var
is an array of three elements. This simplifies iteration significantly.Iterating a Numeric Range
Bash/Zsh
for i in $(seq 1 5);
do
echo "Number: $i"
done
# Or with brace expansion
for i in {1..5};
do
echo "Number: $i"
done
Fish Shell
for i in (seq 1 5)
echo "Number: $i"
end
# Or using math for more complex ranges
for i in (math '1..5')
echo "Number: $i"
end
Iterating Over an Array/List
Bash/Zsh
my_array=("apple" "banana" "cherry")
for item in "${my_array[@]}";
do
echo "Fruit: $item"
done
Fish Shell
set my_array "apple" "banana" "cherry"
for item in $my_array
echo "Fruit: $item"
end
Iterating Over Command Output
Bash/Zsh
for file in $(ls *.txt);
do
echo "Processing file: $file"
done
# Safer way with find
find . -name "*.txt" -print0 | while IFS= read -r -d $'' file;
do
echo "Processing file: $file"
done
Fish Shell
for file in (ls *.txt)
echo "Processing file: $file"
end
# For more robust handling of filenames with spaces, use string split
# This example assumes `find` output is newline-separated
for file in (find . -name "*.txt" | string split \n)
# Ensure 'file' is not empty if find returns nothing or has trailing newline
if test -n "$file"
echo "Processing file: $file"
end
end
Looping with a C-style Counter
Bash/Zsh
for (( i=0; i<5; i++ ));
do
echo "Count: $i"
done
Fish Shell
for i in (seq 0 4)
echo "Count: $i"
end
# Or using a while loop for more complex conditions
set i 0
while test $i -lt 5
echo "Count: $i"
set i (math $i + 1)
end
Best Practices for Fish Shell Loops
When writing loops in Fish Shell, consider these best practices to ensure your code is robust and idiomatic:
- Embrace
seq
andmath
: For numeric ranges,seq
is your friend. For more complex arithmetic within loops,math
provides a powerful and intuitive way to perform calculations. - Leverage Fish's array handling: Fish handles arrays naturally. You rarely need special syntax like
${array[@]}
to expand an array for iteration. - Use
string split
for command output: When iterating over the output of a command, especially if it might contain spaces or special characters,string split
is a powerful tool to parse the output reliably. - Prefer
for
overwhile
for simple iteration: If you're just iterating over a known list or range,for
is generally more concise and readable thanwhile
with a manual counter. - Always
end
your loops: Fish requires an explicitend
keyword to close loop blocks, similar tofi
forif
statements.
# Example: Iterating over files and performing an action
for file in (ls *.log)
if test -f "$file"
echo "Analyzing log file: $file"
# Add your processing logic here, e.g., grep, awk, etc.
grep "ERROR" "$file"
end
end
# Example: Looping with a step increment
for i in (seq 0 2 10) # Start 0, step 2, end 10
echo "Current value: $i"
end
Practical Fish Shell loop examples