Skip to content
shellmap

functionDefine a reusable named function in a shell script across all 5 shells

Equivalents in every shell

Bashunix
greet() { echo "hi $1"; }

POSIX form is `name() { body; }`. Bash also accepts `function name { body; }` and `function name() { body; }`. Arguments are `$1`, `$2`, ..., the count is `$#`, all args are `$@`. `return N` exits with status N.

Zshunix
greet() { echo "hi $1"; }

Identical to bash. Zsh's `function name { ... }` form is preferred in zsh-only scripts because it also enables anonymous functions: `() { body }` runs the body immediately in its own scope.

Fishunix
function greet; echo "hi $argv[1]"; end

Fish uses `function NAME ... end`. Arguments live in `$argv` (a list, 1-indexed). No `return value` — fish functions implicitly return the exit status of the last command. Functions can be auto-loaded from `~/.config/fish/functions/<name>.fish`.

PowerShellwindows
function Greet { param($name) "hi $name" }

Functions are first-class. Named parameters via `param()`, positional via `$args`. Output is collected from EVERY uncaptured expression and returned as an array — explicit `return` is only for early exit.

cmd.exewindows
call :greet World

Cmd has no `function` keyword. Use labels + `call :label arg`. Inside the label, args are `%1`, `%2`, ...; return with `goto :eof`. Variables are global unless `setlocal` is the first line of the label.

Worked examples

Define and call a simple function

Bash
greet() { echo "hi $1"; }; greet Maggie
Zsh
greet() { echo "hi $1"; }; greet Maggie
Fish
function greet; echo "hi $argv[1]"; end; greet Maggie
PowerShell
function Greet { param($n) "hi $n" }; Greet Maggie

Return a value from a function

Bash
add() { echo $(($1 + $2)); }; result=$(add 1 2)
Zsh
add() { echo $(($1 + $2)); }; result=$(add 1 2)
Fish
function add; math $argv[1] + $argv[2]; end; set result (add 1 2)
PowerShell
function Add { param($a, $b) $a + $b }; $result = Add 1 2

Local variables inside a function

Bash
f() { local x=1; echo $x; }
Zsh
f() { local x=1; echo $x; }
Fish
function f; set -l x 1; echo $x; end
PowerShell
function F { $local:x = 1; $x }

Gotchas

  • Bash `return` only returns an EXIT STATUS (0–255 integer), NOT a string or arbitrary value. To "return" a value, `echo` it inside the function and capture with `result=$(func)` at the call site. Returning a string via `return` silently truncates to a uint8.
  • `function name() { ... }` (with parentheses AND the `function` keyword) is BASH-ONLY syntax. POSIX `sh` / dash / ash do not accept it. Use the POSIX `name() { ... }` form for any script intended to run under `/bin/sh`.
  • Fish function arguments live in `$argv` (a list). `$argv[1]` is the FIRST, not `$0` or `$1` like bash. There is no equivalent of bash's `$0` for the function name — use `(status function)` instead, which returns the currently executing function's name.
  • PowerShell functions ACCUMULATE all uncaptured output as the return value. `function F { "hi"; "bye" }` returns the array `@("hi","bye")`, not just "bye". Pipe unwanted output to `| Out-Null` or assign to a variable to suppress it; `return $x` alone does not discard prior output.
  • Cmd `:label` "functions" SHARE all variables with the caller unless `setlocal` is the first line inside the label. `endlocal` is required before `goto :eof` if you want a value to escape; the canonical idiom is `endlocal & set "RESULT=%RESULT%"` on a single line.

WSL & PowerShell Core notes

pwshPowerShell functions are fully portable between Windows, Linux, and macOS pwsh — same `function name { ... }` syntax, same parameter binding, same scoping rules. The accumulated-output return model is a major surprise for newcomers porting bash scripts that use `echo`+`$(...)` to return values.
WSLWSL bash functions defined in `~/.bashrc` are visible only inside WSL. Exporting functions via `export -f greet` and crossing into a Windows-side child process loses them — the function is dropped at the process boundary. Wrap bash logic in a script file if you need to invoke it from Windows pwsh.

Related commands