Skip to content
shellmap

testEvaluate a conditional — file tests, string and number comparisons across all 5 shells

Equivalents in every shell

Bashunix
test -f /etc/hosts

POSIX builtin. `[ -f /etc/hosts ]` is the same command — `[` is a synonym, and the closing `]` is a required argument. Exit 0 if true, 1 if false. For arithmetic + glob extras, prefer `[[ ]]`.

Zshunix
test -f /etc/hosts

Same as bash. Zsh also offers `[[ ]]` extended-test syntax with safer string-comparison semantics — `[[ $var == foo ]]` does not need quoting around `$var`.

Fishunix
test -f /etc/hosts

Fish builtin. Fish has NO `[[ ]]`; `test` is the only conditional primitive. Combine results with the keywords `and` / `or` / `not` (not `&&` / `||`).

PowerShellwindows
Test-Path /etc/hosts

No single `test` cmdlet. `Test-Path` handles file/directory existence; comparison operators (`-eq`, `-lt`, `-gt`, `-match`) handle everything else. Both return `$true` / `$false`, not POSIX exit codes.

cmd.exewindows
if exist C:\Windows\System32 (echo yes)

Cmd has no `test` keyword. The `if` builtin includes `exist`, `defined`, `errorlevel`, and `==`. Number comparison uses `equ` / `lss` / `gtr` (`if %n% gtr 10 echo big`).

Worked examples

Branch on whether a file exists

Bash
if [ -f /etc/hosts ]; then echo present; fi
Zsh
if [[ -f /etc/hosts ]]; then echo present; fi
Fish
if test -f /etc/hosts; echo present; end
PowerShell
if (Test-Path /etc/hosts) { "present" }
cmd.exe
if exist C:\Windows\System32\drivers\etc\hosts echo present

Compare two integers (n greater than 10)

Bash
test "$n" -gt 10 && echo big
Zsh
(( n > 10 )) && echo big
Fish
test "$n" -gt 10; and echo big
PowerShell
if ($n -gt 10) { "big" }
cmd.exe
if %n% gtr 10 echo big

Check whether a string variable is non-empty

Bash
[ -n "$VAR" ] && echo set
Fish
test -n "$VAR"; and echo set
PowerShell
if ($VAR) { "set" }
cmd.exe
if defined VAR echo set

Gotchas

  • `test` / `[` REQUIRES whitespace around its arguments — `[ -f /etc/hosts ]` works, `[-f /etc/hosts]` (no spaces) is a syntax error. The `[` is a literal command name, not parser sugar.
  • Unquoted variables in `[ ]` are a classic bug: `[ -n $VAR ]` becomes `[ -n ]` (always true) when `$VAR` is empty. ALWAYS double-quote: `[ -n "$VAR" ]`. Bash/zsh `[[ ]]` avoids this trap entirely.
  • Bash `[[ ]]` and POSIX `[ ]` are NOT interchangeable — `[[ ]]` supports `==` pattern matching and `=~` regex, while `[ ]` does not. Scripts intended for `/bin/sh` (`#!/bin/sh`) must stay POSIX and use only `[ ]`.
  • PowerShell `-eq` is CASE-INSENSITIVE for strings by default (`"A" -eq "a"` is `$true`). Use `-ceq` for case-sensitive or `-ieq` for explicit insensitive. Bash `[ "$a" = "$b" ]` is always case-sensitive — porting scripts must reconcile the difference.
  • Cmd `if` does NOT support file-attribute tests (no `-x`, `-r`, etc.). The only file-related operator is `exist`. For permissions checks, drop to PowerShell `Test-Path` + ACL lookups or use `icacls` parsing.

WSL & PowerShell Core notes

pwsh`Test-Path` and the comparison operators (`-eq`, `-lt`, `-gt`, `-match`) work identically on Windows, Linux, and macOS pwsh. Watch the case-insensitivity default: `"A" -eq "a"` is `$true` on every platform — use `-ceq` for case-sensitive comparisons even when porting from Linux scripts where `[ "$a" = "$b" ]` is always case-sensitive.
WSLInside WSL `test` / `[` is the bash builtin and behaves like native Linux. Crossing the WSL ↔ Windows filesystem boundary, paths require translation: `test -f /mnt/c/Windows/System32/drivers/etc/hosts` works, `test -f "C:\Windows\..."` does not — only forward-slashes and the `/mnt/<drive>` prefix are valid inside WSL.

Common tasks using test

Related commands