Introduction to Arithmetic in Fish
Fish shell offers a clean, built-in approach to mathematical calculations through its
math command. Unlike legacy shells that rely on external tools like expr or
bc, Fish treats arithmetic as a first-class operation, supporting both integer and
floating-point math with a familiar expression syntax. This guide covers everything you need
to perform calculations inside your Fish scripts and interactive sessions.
What is the math Command?
math is a Fish builtin that evaluates a mathematical expression provided as an
argument and prints the result to standard output. It understands standard operators, functions,
parentheses, and can handle numbers in decimal, hexadecimal, or octal bases. Because it is a
builtin, it starts quickly and integrates seamlessly with Fish’s command substitution and
variable assignment.
Why Arithmetic Matters in Shell Scripts
Shell scripts frequently need to count items, calculate offsets, convert units, or make numeric comparisons. Reliable arithmetic lets you:
- Loop a precise number of times
- Generate numbered file names or backup rotations
- Perform floating-point division for progress percentages
- Manipulate bit flags and permissions
- Validate user input ranges
Using Fish’s math keeps your scripts portable, readable, and free from dependency
on system utilities like awk or bc.
Using math for Basic Arithmetic
🚀 Deploy your AI agent in 10 minutes
Managed Hermes hosting. Zero DevOps. 100M tokens/mo included.
Try it free →The simplest invocation passes a quoted expression. Quotes prevent Fish from interpreting parentheses or asterisks as glob characters. The result is printed with a trailing newline.
# Basic addition
math "2 + 2"
# Multiplication and division
math "5 * 3"
math "10 / 3" # outputs 3.3333333333 (floating point by default)
# Subtraction and negation
math "7 - 2"
math "-4 + 1"
Integer and Floating-Point Operations
Fish’s math automatically uses floating-point arithmetic when the expression involves
division or when you supply decimal numbers. For pure integer operations, the result is still
printed as an integer but the internal computation uses floating-point precision. To force
integer-only behavior (truncation), use functions like floor or ceil.
# Floating-point by default
math "5 / 2" # 2.5
# Explicit integer via truncation
math "floor(5 / 2)" # 2
# Mixed integer and float
math "3.14 * 2" # 6.28
Operator Precedence and Parentheses
The math command follows standard mathematical precedence: parentheses first, then
multiplication/division/modulo, followed by addition/subtraction. Use parentheses to group
subexpressions clearly.
# Precedence: multiplication before addition
math "2 + 3 * 4" # 14
# Explicit grouping
math "(2 + 3) * 4" # 20
# Complex expression
math "(10 - 3) * (2 + 1) / 7"
Assignment and Command Substitution
To capture the output of math in a variable, use command substitution with
(). The parentheses run the math command in a subshell and expand to its
result. This is the idiomatic way to store computed values in Fish.
# Simple assignment
set result (math "10 + 5")
echo $result # 15
# Use variables inside expression
set a 42
set b 8
set sum (math "$a + $b")
echo "The sum is $sum"
# Multiple assignments in a pipeline
set width (math "1920 / 2")
set height (math "1080 / 2")
echo "Half resolution: $width x $height"
Important: Always quote the expression containing variable expansions to preserve spaces and special characters. If the expression contains only numbers and operators, the quotes can sometimes be omitted, but quoting is safer.
Advanced Arithmetic Features
Beyond basic operators, Fish’s math supports bitwise operations, rounding, base
conversion, and a range of mathematical functions. These make it suitable for low-level
calculations and data processing.
Bitwise Operations
Use functions bitand, bitor, bitxor, bitnot, and
shift functions shl (shift left) and shr (shift right). These are
invoked as function calls inside the expression string.
# Bitwise AND
math "bitand(5, 3)" # 1 (0101 & 0011 = 0001)
# Bitwise OR
math "bitor(8, 2)" # 10
# Shift left
math "shl(1, 4)" # 16 (1 << 4)
# Shift right
math "shr(16, 2)" # 4
# Bitwise NOT (two's complement)
math "bitnot(0)" # -1 on most systems
Rounding and Scale Control
The --scale option sets the number of decimal places for the result. Default is
usually 10. You can reduce it for cleaner output or increase for higher precision. Common
rounding functions include ceil, floor, and round.
# Default high precision
math "22 / 7" # 3.142857142857...
# Limit to 2 decimals
math --scale 2 "22 / 7" # 3.14
# Round to nearest integer
math "round(3.6)" # 4
# Floor and ceiling
math "floor(3.2)" # 3
math "ceil(3.2)" # 4
# Combine scale and rounding
math --scale 1 "round(9.876, 1)" # 9.9
Using Math in Conditionals
Because math returns a numeric exit code (0 for success, non-zero for failure),
you can directly use it in if statements. A true/false test evaluates the expression
and returns 0 if the result is non-zero, or 1 if zero. This behaves like boolean logic.
# Check if a number is greater than another
set a 10
set b 5
if math "$a > $b" > /dev/null
echo "$a is greater than $b"
end
# Compare equality
if math "$a == $b" > /dev/null
echo "equal"
else
echo "not equal"
end
# Test complex conditions
set count 3
if math "$count >= 1 && $count <= 5" > /dev/null
echo "count is in range"
end
The > /dev/null redirection discards the actual numeric result, keeping only the
exit status for the condition. Alternatively, you can capture the result and compare with
test.
Math with Variables and Arrays
Fish variables expand directly inside the quoted expression. For arrays, you may need to reduce
them to a single value or iterate. Use count to get array length and perform
calculations on indices.
# Using array length
set files *.fish
set count (count $files)
set avg_per_dir (math "$count / 3") # integer division with floor if needed
# Iterate with index arithmetic
for i in (seq 1 10)
set doubled (math "$i * 2")
echo "Index $i doubled is $doubled"
end
# Combine math with string manipulation
set size_str "42kb"
set num_only (string match --regex '\d+' $size_str)
set bytes (math "$num_only * 1024")
echo "$size_str is approximately $bytes bytes"
Best Practices for Fish Arithmetic
-
Prefer
mathover external tools. Avoidexpr,bc, orawkfor simple arithmetic.mathis faster, always available, and integrates naturally with Fish’s syntax. -
Always quote the expression.
Unquoted parentheses or asterisks trigger file globbing, leading to unexpected errors.
math "2 * (3 + 1)"is safe;math 2 * (3 + 1)may fail. -
Use
--scalefor decimal precision. When you need exactly two decimal places (e.g., currency), set the scale explicitly to avoid long trailing digits. -
Check exit status when used conditionally.
The expression result of 0 is falsy; any non-zero is truthy. Redirect output to
/dev/nullwhen you only care about the boolean outcome. -
Handle errors gracefully.
If a syntax error occurs (like unbalanced parentheses),
mathreturns a non-zero exit status and prints an error to stderr. Consider wrapping inifor usingorto provide fallback values. - Use functions for repetitive calculations. Wrap common math patterns in Fish functions to keep scripts DRY and improve readability.
-
Validate variable content.
Ensure variables used in expressions contain numeric strings. Use
string matchto sanitize input before passing tomath.
Conclusion
Fish’s math command gives you a powerful, self-contained calculator that eliminates
dependence on legacy Unix utilities. With support for floating-point, bitwise operations, rounding,
and seamless integration into Fish’s control flow, it handles everything from simple counter
updates to complex conditional logic. By quoting expressions, controlling scale, and leveraging
command substitution, you can write clean, maintainable shell scripts that perform reliable
arithmetic in any environment. The next time you need to crunch numbers in a script, reach for
math — it’s the Fish way.