Comparing oh to other Unix shells
Grammar
bash | fish | oh | tcsh | zsh | |
---|---|---|---|---|---|
simple command | ls | ls | ls | ls | ls |
simple command with argument | echo hi | echo hi | echo hi | echo hi | echo hi |
simple command with redirect | ls > /tmp/ls.out | ls > /tmp/ls.out | ls > /tmp/ls.out | ls > /tmp/ls.out | ls > /tmp/ls.out |
simple command with environment variable | EDITOR=vi git commit | env EDITOR=vi git commit | EDITOR=vi git commit | env EDITOR=vi git commit | EDITOR=vi git commit |
pipeline | ls | wc | ls | wc | ls | wc | ls | wc | ls | wc |
sublist separators | && || | none | && || | && || | && || |
list terminators | ; & | ; & | & | ; & | ; & |
group command | { ls; ls;} | wc | begin; ls; ls; end | wc | ls; ls | wc | none | { ls; ls;} | wc |
subshell | (ls; ls) | wc | fish -c 'ls; ls' | wc | oh -c 'ls; ls' | wc | (ls; ls) | wc | (ls; ls) | wc |
Quoting and Escaping
bash | fish | oh | tcsh | zsh | |
---|---|---|---|---|---|
literal quotes | 'foo' | 'foo' | 'foo' | 'foo' | 'foo' |
interpolating quotes | foo=7 echo "foo is $foo" |
set foo 7 echo "foo is $foo" |
define foo 7 echo "foo is $foo" |
setenv foo 7 echo "foo is $foo" |
foo=7 echo "foo is $foo" |
interpolating quotes escape sequences | \$ \\ \` \" | \" \$ \\ | $$ \\ \" | none | \$ \\ \` \" |
quotes with backslash escapes | $'foo\n' | none | "foo\n" | none | $'foo' |
quoted backslash escapes | \a \b \e \E \f \n \r \t \v \\ \' \" \ooo \xhh \cctrl |
none | \a \b \f \n \r \t \v \\ \" \ooo \xhh \uhhhh \Uhhhhhhhh |
none | \a \b \e \E \f \n \r \t \v \\ \' \" \ooo \xhh \cctrl |
unquoted backslash escapes | \space | \a \b \e \f \n \r \t \v \space \$ \\ \* \? \~ \% \# \( \) \{ \} \[ \] \< \> \^ \& \; \" \' \xhh \Xhh \ooo \uhhhh \Uhhhhhhhh \cctrl |
none | \space | \space |
command substitution | $(ls) `ls` |
(ls) | `(ls) | `ls` | $(ls) `ls` |
backtick escape sequences | \$ \\ \` \newline | none | none | \$ \\ \newline | \$ \\ \` \newline |
Characters
bash | fish | oh | tcsh | zsh | |
---|---|---|---|---|---|
word separating | | & ; ( ) < > SP HT LF | | & ; ( ) < > SP HT LF | | & ; ( ) < > SP HT LF | | & ; ( ) < > SP HT LF | | & ; ( ) < > SP HT LF |
quoting and escaping | " ' \ | " ' \ | " ' | " ' \ | " ' \ |
shell expansion | variable: $ brace: { } tilde: ~ command: ` pathname: * ? [ ] history: ! ^ |
variable: $ brace: { } tilde: ~ command: ( ) pathname: * ? |
variable: $ tilde: ~ command: ` pathname: * ? [ ] |
variable: $ brace: { } tilde: ~ command: ` pathname: * ? [ ] history: ! ^ |
variable: $ brace: { } tilde: ~ command: ` pathname: * ? [ ] history: ! ^ |
other special | # = | # [ ] | # | # | # = |
bareword | A-Z a-z 0-9 _ - . , : + / @ % | A-Z a-z 0-9 _ - . , : + / @ % ! ^ = | A-Z a-z 0-9 _ - . , : + / @ % ! ^ = * ? [ ] ~ | A-Z a-z 0-9 _ - . , : + / @ % = | A-Z a-z 0-9 _ - . , : + / @ % |
variable name | A-Z a-z 0-9 _ | A-Z a-z 0-9 _ | A-Z a-z 0-9 _ - . , : + / @ % ! ^ = * ? [ ] ~ | A-Z a-z 0-9 _ | A-Z a-z 0-9 _ |
Variables
bash | fish | oh | tcsh | zsh | external | |
---|---|---|---|---|---|---|
global variables set, get, list, unset, edit |
var=val $var set unset -v var none |
set -g var val $var set -g set -e var vared var |
define var val $var (Variables not global by default). |
set var=val $var set unset var none |
var=val $var set unset -v var vared var |
|
read-only variables mark readonly, set and mark readonly, list readonly |
readonly var readonly var=val readonly -p |
none | none | none | readonly var readonly var=val readonly -p |
|
exported variables export, set and export, list exported, undo export |
export var export var=val export -p export -n var |
set -gx var $var set -gx var val set -x set -gu var $var |
none export var val none none |
setenv var $var setenv var val printenv none |
export var export var=val export -p none |
none none printenv none |
options set, list, unset |
set -o opt set -o set +o opt |
none | none | none | set -o opt set -o set +o opt |
|
other variable built-ins | declare | @ | declare functions setopt float integer unsetopt |
Variable Expansion
bash | fish | oh | tcsh | zsh | external | |
---|---|---|---|---|---|---|
set variable value | var=val | set -g var val | set var val | setenv var val | var=val | |
get variable value | $var | $var | $var | $var | $var | |
concatenate variable and value | ${var}val | {$var}val | ${var}val | ${var}val | ${var}val | |
coalesce | ${var:-val} | coalesce $var val | ${var:-val} | |||
coalesce and assign if null | ${var:=val} | ${var:=val} | ||||
message to stderr and exit if null | ${var:?msg} | ${var:?msg} | ||||
substring | offset is zero based: ${var:offset} ${var:offset:len} |
str slice $var start str slice $var start stop |
offset is zero based: ${var:offset} ${var:offset:len} |
offset is one based; when input lacks newlines: awk '{print substr($0, offset, len)}' |
||
length | ${#var} | str length $var | ${%var} | ${#var} | wc -m | |
remove prefix greedily | foo=do.re.mi ${foo##*.} |
foo=do.re.mi ${foo##*.} |
sed 's/^.*\.' | |||
remove prefix reluctantly | foo=do.re.mi ${foo#*.} |
foo=do.re.mi ${foo#*.} |
sed 's/^[^\.]*\.' | |||
remove suffix greedily | foo=do.re.mi ${foo%%.*} |
foo=do.re.mi ${foo%%.*} |
sed 's/\..*$' | |||
remove suffix reluctantly | foo=do.re.mi ${foo%.*} |
foo=do.re.mi ${foo%.*} |
sed 's/\.[^\.]*$' | |||
single substitution | foo='do re mi mi' ${foo/mi/ma} |
foo='do re mi mi' ${foo/mi/ma} |
sed 's/mi/ma/' | |||
global substitution | foo='do re mi mi' ${foo//mi/ma} |
foo='do re mi mi' ${foo//mi/ma} |
sed 's/mi/ma/g' | |||
prefix substitution | foo=txt.txt ${foo/#txt/text} |
foo=txt.txt ${foo/#txt/text} |
sed 's/^txt/text/' | |||
suffix substitution | foo=txt.txt ${foo/%txt/html} |
foo=txt.txt ${foo/%txt/html} |
sed 's/txt$/html/' | |||
upper case | foo=lorem ${foo^^} |
str upper $var | foo=lorem ${foo:u} |
tr '[:lower:]' '[:upper:]' | ||
upper case first letter | foo=lorem ${foo^} |
none | none | |||
lower case | foo=LOREM ${foo,,} |
str lower $var | foo=LOREM ${foo:l} |
tr '[:upper:]' '[:lower:]' | ||
lower case first letter | foo=LOREM ${foo,} |
none | none | |||
absolute path | define foo ~ readlink -f $foo |
foo=~ ${foo:a} |
||||
dirname | define foo /etc/hosts dirname $foo |
foo=/etc/hosts ${foo:h} |
foo=/etc/hosts dirname $foo |
|||
basename | define foo /etc/hosts basename $foo |
foo=/etc/hosts ${foo:t} |
foo=/etc/hosts basename $foo |
|||
extension | foo=index.html ${foo:e} |
|||||
root | foo=index.html ${foo:r} |
Brace, Tilde, Command, and Pathname Expansion
bash | fish | oh | tcsh | zsh | |
---|---|---|---|---|---|
brace expansion: list | echo {foo,bar} | echo {foo,bar} | none | echo {foo,bar} | echo {foo,bar} |
brace expansion: sequence | echo {1..10} | none | none | none | echo {1..10} |
brace expansion: character sequence | echo {a..z} | none | none | none | none |
tilde expansion | echo ~/bin | echo ~/bin | echo ~/bin | echo ~/bin | echo ~/bin |
command expansion: dollar parens | echo $(ls) | echo (ls) | echo `(ls) | none | echo $(ls) |
command expansion: backticks | echo `ls` | none | none | echo `ls` | echo `ls` |
process substitution | wc <(ls) | wc (ls | psub) | wc |<(ls) | none | wc <(ls) |
path expansion: string | echo /bin/c* | echo /bin/c* | echo /bin/c* | echo /bin/c* | echo /bin/c* |
path expansion: character | echo /bin/c?? | echo /bin/c?? | echo /bin/c?? | echo /bin/c?? | echo /bin/c?? |
path expansion: character set | echo /bin/[cde]* | none | echo /bin/[cde]* | echo /bin/[cde]* | echo /bin/[cde]* |
path expansion: negated character set | echo /bin/[^cde]* | none | echo /bin/[^cde]* | echo /bin/[^cde]* | echo /bin/[^cde]* |
path expansion: sequence of characters | echo /bin/[a-f]* | none | echo /bin/[a-f]* | echo /bin/[a-f]* | echo /bin/[a-f]* |
Special Variables
in zsh terminology, special means read-only variables that cannot have their type changed
non-alphabetical variables | |||||
---|---|---|---|---|---|
bash | fish | oh | tcsh | zsh | |
name of shell or shell script | $0 | (status -f) | $0 | $0 | $0 |
command line arguments | $1, $2, … | $argv[1], $argv[2], … | $1, $2, … | $1, $2, … | $1, $2, … $argv[1], $argv[2], … |
number of command line args | $# | (count $argv) | (@ length) | $# | $# $#argv |
arguments $1, $2, … | $* $@ |
none | $@ | $* | $* $@ |
"$1" "$2" "$3" … | "$@" | $argv | (splice $@) | "$@" | |
"$1c$2c$3 …" where c is first character of $IFS | "$*" | "$argv" | (mend "c" (splice $@)) | "$*" | |
process id | $$ | %self | $$ | $$ | $$ |
process id of last asynchronous command | $! | none | none | $! | $! |
exit status of last non-asynchronous command | $? | $status | $? | $? | $? |
previous command executed | $_ | current command executing: $_ |
none | $_ | $_ |
command line options | $- | none | none | none | $- |
read input | none | none | none | $< | none |
set by shell | |||||
---|---|---|---|---|---|
bash | fish | oh | tcsh | zsh | |
shell version | BASH_VERSION | tcsh | ZSH_VERSION | ||
return value of last syscall | ERRNO | ||||
history | history | ||||
current line number of script | LINENO | LINENO | |||
set by getopts | OPTARG OPTIND |
OPTARG OPTIND |
|||
operating system and machine type | OSTYPE MACHTYPE |
||||
shell parent pid | PPID | PPID | |||
working directory and previous working directory | PWD OLDPWD |
PWD none |
PWD OLDPWD |
PWD OLDPWD |
|
random integer | RANDOM | built-in function: random |
built-in function: random |
RANDOM | |
return value | REPLY | REPLY | |||
seconds since shell was invoked | SECONDS | SECONDS | |||
incremented each time a subshell is called | SHLVL | SHLVL |
read by shell | |||||
---|---|---|---|---|---|
bash | fish | oh | tcsh | zsh | |
browser | BROWSER | ||||
cd search path | CDPATH | CDPATH | cdpath | CDPATH cdpath |
|
terminal width and height | COLUMNS LINES |
||||
command history editor | FCEDIT EDITOR |
FCEDIT EDITOR |
|||
shell startup file | ENV | ENV | |||
function definition search path | fpath FPATH |
||||
history file path | HISTFILE | HISTFILE | |||
size of history | HISTSIZE | HISTSIZE | |||
home directory | HOME | HOME | HOME | HOME | |
input field separators | IFS | IFS | |||
locale | LANG | LANG | LANG | ||
null redirect command | NULLCMD READNULLCMD |
||||
command search path | PATH | PATH | PATH | PATH | |
prompt customization main, secondary, select, trace |
PS1 PS2 PS4 | PS1 PS2 PS3 PS4 | |||
right prompt customization | RPS1 RPS2 | ||||
terminal type | TERM | TERM | |||
timeout | TMOUT | ||||
system tmp directory | TMPDIR | ||||
user | USER |
Arithmetic and Conditional Expressions
bash | fish | oh | tcsh | zsh | |
---|---|---|---|---|---|
test command | [ -e /etc ] test -e /etc |
[ -e /etc ] test -e /etc |
[ -e /etc ] test -e /etc |
[ -e /etc ] test -e /etc |
|
true command | true | true | true | true | |
false command | false | false | false | false | |
conditional command | [[ ]] | [[ ]] | |||
conditional expression | ( ) | ||||
arithmetic expansion | $(( 1 + 1 )) | math '1 + 1' | math '1 + 1' | $(( 1 + 1 )) | |
floating point expansion | none | math '1.1 + 1.1' | math '1.1 + 1.1' | $(( 1.1 + 1.1 )) | |
let expression | let "var = expr" | let "var = expr" | |||
external expression | expr 1 + 1 expr 0 '<' 1 |
expr 1 + 1 expr 0 '<' 1 |
expr 1 + 1 expr 0 '<' 1 |
expr 1 + 1 expr 0 '<' 1 |
expr 1 + 1 expr 0 '<' 1 |
arithmetic command | (( )) | (( )) | |||
eval | while true; do read -p '$ ' cmd eval $cmd done |
while true read cmd eval $cmd end |
while (define cmd: read) { eval $cmd } |
while (1) echo -n '% ' eval $< end |
while true; do read cmd\?'$ ' eval $cmd done |
Arrays
bash | fish | oh | tcsh | zsh | |
---|---|---|---|---|---|
declare | typeset -a var | none | define var: list | none | typeset -a var |
list all arrays | typeset -a | none | none | none | typeset -a |
literal | a=(do re mi) | set a do re mi | define a: list do re mi | set a = (do re mi) | a=(do re mi) |
lookup | ${a[0]} | $a[1] | a get 0 | ${a[1]} | ${a[1]} $a[1] |
negative index lookup | returns last element: ${a[-1]} |
returns last element: $a[-1] |
returns last element: a get -1 |
none | returns last element: ${a[-1]} |
slice | ${a[@]:2:3} ${a[*]:2:3} |
$a[(seq 2 3)] | a slice 1 2 | ${a[2-3]} | $a[2,3] |
update | a[0]=do a[1]=re a[2]=mi |
set a[1] do set a[2] re set a[3] mi |
none | set a[1] = do set a[2] = re set a[3] = mi |
a[1]=do a[2]=re a[3]=mi |
out-of-bounds behavior | lookup returns empty string update expands array; array can have gaps |
error message and nonzero exit status update expands array; in-between slots get empty strings |
lookup and update both cause an exception |
lookup and update both produce error message and nonzero exit status |
lookup returns empty string update expands array; in-between slots get empty strings |
size | highest index: ${#a[@]} ${#a[*]} |
count $a | a length | ${#a} | ${#a} ${#a[@]} ${#a[*]} |
list indices | can contain gaps: ${!a[@]} ${!a[*]} |
(seq (count $a)) | seq (a length) | `seq ${#a}` | $(seq ${#a}) |
regular reference | return first element | return all elements joined by space | return list | return all elements joined by space | return all elements joined by space |
regular assignment | assigns to 0-indexed slot | convert array to regular variable | variable references new value | convert array to regular variable | convert array to regular variable |
delete element | unset a[0] | set -e a[1] re is now at index 1 |
a[0]=() | ||
delete array | unset a[@] unset a[*] |
set -e a | unset -v a | ||
pass each element as argument | cmd "${a[@]}" | cmd $a | cmd (splice $a) | cmd "${a[@]}" | |
pass as single argument | cmd "${a[*]}" | cmd "$a" | cmd (mend ' ' (splice $@)) | cmd "${a[*]}" |
Associative Arrays
bash | fish | oh | tcsh | zsh | |
---|---|---|---|---|---|
declare | typeset -A var | none | define var: map | none | typeset -A var |
list all associative arrays | typeset -A | none | none | none | typeset -A |
assign value | var[bar]=baz | none | var set "bar" baz | none | var[bar]=baz |
lookup | ${var[bar]} | none | var get "bar" | none | ${var[bar]} |
list indices | ${!var[@]} ${!var[*]} |
none | none | none | none |
delete value | unset "var[bar]" | none | var del "bar" | none | unset "var[bar]" |
delete array | unset "var[@]" | none | none | none | unset -v var |
Functions
bash | fish | oh | tcsh | zsh | |
---|---|---|---|---|---|
define with parens | foo() { echo foo } |
none | none | foo() { echo foo } |
|
define with keyword | function foo { echo foo } |
function foo echo foo end |
define foo: method () { echo foo } |
none | function foo { echo foo } |
define with doc string | function foo -d 'echo foo' echo foo end |
||||
edit function definition | funced foo | in .zshrc: autoload -U zed ^J when done: zed -f foo |
|||
parameters | $1, $2, … | $argv[1], $argv[2], … | Given: define foo: method ((argv)) { # ... } argv get 0, argv get 1, … |
none | $1, $2, … |
number of parameters | $# | (count $argv) | (argv length) | none | $# |
return | false() { return 1 } |
function false return 1 end |
define false: method () { return () } |
none | false() { return 1 } |
return values | {0, …, 255} | {0, …, 2**31 - 1} negative values result in return value of "-" values above 2**31 - 1 cause error |
The complete set of oh data types. | none | {-2**31, …, 2**31 - 1} other integers converted to one of the above values by modular arithmetic |
local variables | foo() { local bar=7 } variables set without the local keyword are global |
function foo set -l bar 7 end without the -l flag, the the variable will be global if already defined, otherwise local |
define foo: method () { define bar 7 } |
none | foo() { local bar=7 } variables set without the local keyword are global |
list functions | typeset -f | grep '()' | functions | none | typeset -f | grep '()' | |
show function | typeset -f func | functions func | typeset -f func | ||
delete function | unset -f func | functions -e func | none | unset -f func unfunction foo |
Command Resolution
bash | fish | oh | tcsh | zsh | |
---|---|---|---|---|---|
alias: define, list, remove, define suffix alias |
alias ll='ls -l' alias unalias ll none |
alias ltr 'ls -ltr' functions functions -e ltr none |
define ll: method ((args)) { ls -l (splice $args) } |
alias ll ls -l alias unalias ll none |
alias ll='ls -l' alias -L unalias ll alias -s txt=cat |
built-ins: run, list, help, enable, disable |
builtin cmd enable -a help cmd enable cmd enable -n cmd |
builtin cmd builltin -n cmd --help none none |
none none none none none |
none builtins none none none |
builtin cmd none type command name; then M-h enable cmd disable cmd |
run external command | command cmd | command cmd | command cmd | command cmd | |
run with explicit environment | env -i var=val … cmd args … | ||||
external command hashes: list, set, delete from, clear, rebuild |
hash none hash -d cmd hash -r none |
does not cache command paths | does not cache command paths | none none none rehash none |
hash hash cmd=path unhash hash -r hash -f |
command type | type cmd | type cmd | type cmd | ||
command path | command -v cmd | whence cmd | command -v cmd which cmd whence cmd |
||
command paths | where cmd | where cmd which -a cmd |
Arguments and Options
bash | fish | oh | tcsh | zsh | |
---|---|---|---|---|---|
execute command and exit | $ bash -c 'echo foo' | $ fish -c 'echo foo' | $ oh -c 'echo foo' | $ tcsh -c 'echo foo' | $ zsh -c 'echo foo' |
usage | $ bash --help | $ fish --help | $ tcsh --help | $ zsh --help | |
interactive shell | $ bash -i | $ fish -i | $ tcsh -i | $ zsh -i | |
login shell | $ bash -l $ bash --login |
$ fish -l $ fish --login |
$ tcsh -l | $ zsh -l $ zsh --login |
|
make posix compliant | $ bash --posix | ||||
restricted mode | $ bash -r $ bash --restricted |
$ zsh -r $ zsh --restricted |
|||
show version | $ bash --version | $ fish --version | $ tcsh --version | $ zsh --version | |
shift positional parameters: by one, by n |
shift shift n |
set @ (@ tail) none |
shift none |
shift shift n |
|
set positional parameters | set -- arg … | set @ = … | set -- arg … | ||
getopts | getopts opts var | getopts opts var |
Execution Control
bash | fish | oh | tcsh | zsh | |
---|---|---|---|---|---|
negate exit status | ! cmd | not cmd | not: cmd | ! cmd | |
no-op command | : | : | : | ||
break | break | break | break | break | |
case | case arg in pattern) cmd;; … *) cmd;; esac |
switch arg case pattern … cmd … … case '*' cmd … end |
switch (arg) case pattern: cmd … breaksw … default: cmd … breaksw endsw |
case arg in pattern) cmd;; … *) cmd;; esac |
|
continue | continue | continue | continue | continue | |
for | for var in arg … do cmd … done |
for var in arg … cmd … end |
for list (method (var) { cmd … }) |
foreach var (arg …) cmd … end |
for var in arg … do cmd … done |
goto | goto label | ||||
if | if test then cmd … elif test then cmd … else cmd … fi |
if test cmd … else if test cmd … else cmd … end |
if expr { cmd … } else if expr { cmd … } else { cmd … } |
if (expr) then cmd … else if (expr) then cmd … else cmd … endif |
if test then cmd … elif test then cmd … else cmd … fi |
repeat | repeat count cmd | repeat count do cmd … done |
|||
select | select var in arg … do cmd … done |
select var in arg … do cmd … done |
|||
until | until test do cmd … done |
until test do cmd … done |
|||
while | while test do cmd … done |
while test cmd … end |
while expr { cmd … } |
while (expr) cmd … end |
while test do cmd … done |
Redirection
bash | fish | oh | tcsh | zsh | |
---|---|---|---|---|---|
stdin from file | tr a-z A-Z < file | tr a-z A-Z < file | tr a-z A-Z < file | tr a-z A-Z < file | tr a-z A-Z < file |
stdout to file | ls > file | ls > file | ls > file | ls > file | ls > file |
stderr to file | ls /not_a_file 2> file | s /not_a_file 2> file | none | none | ls /not_a_file 2> file |
stdout and stderr to file | ls > file 2>&1 | ls > file 2>&1 | ls >& file | ls >& file | ls > file 2>&1 |
append stdout to file | ls >> file | ls >> file | ls >> file | ls >> file | ls >> file |
append stderr to file | ls 2>> file | ls 2>> file | none | none | ls 2>> file |
append stdout and stderr to file | ls >> /tmp/bash.out 2>&1 | ls >> /tmp/bash.out 2>&1 | ls >>& file | ls >>& file | ls >> /tmp/zsh.out 2>&1 |
stdout to pipe | ls | wc | ls | wc | ls | wc | ls | wc | ls | wc |
stderr to pipe | none | none | none | none | none |
sdout and stderr to pipe | ls 2>&1 | wc | ls 2>&1 | wc | ls |& wc | ls |& wc | ls 2>&1 | wc |
stdin from here-document | wc << EOF do re mi EOF |
none | none | wc << EOF do re mi EOF |
wc << EOF do re mi EOF |
stdin from here-string | wc <<< "do re mi" | none | none | none | wc <<< "do re mi" |
tee stdout | ls | tee file | wc | ls > file | wc | |||
stdout to two files | ls | tee file1 | tee file2 > /dev/null | ls > file1 > file2 | |||
turn on noclobber | set -o noclobber | noclobber is the default | set noclobber | set -o noclobber | |
clobber file anyways | ls >! /tmp/exists.txt | ls >| /tmp/exists.txt | ls >! /tmp/exists.txt | ls >! /tmp/exists.txt | |
turn off noclobber | set +o noclobber | unset noclobber | set +o noclobber |
Echo and Read
bash | fish | oh | tcsh | zsh | |
---|---|---|---|---|---|
echo with newline, without newline |
echo arg … echo -n arg … |
echo arg … echo -n arg … |
echo arg … echo -n arg … |
echo arg … echo -n arg … |
echo arg … echo -n arg … |
printf | printf fmt arg … | printf fmt arg … | printf fmt arg … | printf fmt arg … | printf fmt arg … |
read read values separated by IFS; with prompt; without backslash escape |
read var … read -p str var read -r var … |
read var … read -p 'echo str' var |
define var: read |
echo -n str set var=$< |
read var … read var\?str read -r var … |
Files and Directories
bash | fish | oh | tcsh | zsh | |
---|---|---|---|---|---|
change current directory change dir, to home dir, to previous dir, show physical dir, no symlink dir |
cd dir cd cd - cd -P dir none |
cd dir cd cd - none none |
cd dir cd cd - none none |
cd dir cd cd - none none |
cd dir cd cd - cd -P dir cd -s dir |
directory stack: push, pop, list |
pushd dir popd dirs |
pushd dir popd dirs |
pushd dir popd dirs |
pushd dir popd dirs |
|
print current directory | pwd | pwd | pwd | pwd | pwd |
source | source file arg … . file arg … |
source file . file |
source file |
source file arg … | source file arg … . file arg … |
umask set umask in octal, in symbolic chmod format; show umask in octal, in symbolic chmod format |
umask 022 umask g-w,o-w umask umask -S |
umask 022 umask g-w,o-w umask umask -S |
umask 022 none umask none |
umask 022 none umask none |
umask 022 umask g-w,o-w umask umask -S |
Process and Job Control
bash | fish | oh | tcsh | zsh | |
---|---|---|---|---|---|
run job in background | bg | bg | bg | bg | bg |
protect job from hangup signal | disown | does not SIGHUP background jobs on exit | does not SIGHUP background jobs on exit | disown | |
execute file | exec [-c] | exec | exec | exec | |
exit | exit [n] | exit | exit [n] | exit | exit bye |
run job in foreground | fg | fg | fg | fg | fg |
hup | |||||
list jobs | jobs [-lnprs] | jobs | jobs | jobs | jobs |
send signal | kill | external, but … kill |
external, but … kill |
kill | kill |
limit | limit | ||||
login | |||||
logout | logout | logout | |||
nice | |||||
nohup | |||||
onintr | |||||
sched | sched | ||||
stop | |||||
suspend | suspend | suspend | |||
time | time | ||||
times | times | ||||
trap | trap | (Not yet implemented) trap |
trap | ||
ulimit | ulimit | ||||
ulimit | unlimit | unlimit | |||
wait | wait | wait | wait |
History
history commands | |||||
---|---|---|---|---|---|
bash | fish | oh | tcsh | zsh | |
command history: list recent, list all, list with time, unnumbered list |
fc -l history set HISTTIMEFORMAT fc -ln |
history | nl | head history | nl cat ~/.config/fish/fish_history history |
none none none cat ~/.oh_history | history 15 history history -T none |
history history 1 history -f history -n |
command history: run, find and run |
!num fc -s str |
none none |
!num ?? |
||
command history: delete from history, clear history |
history -d num history -c |
none history -c |
none none |
||
command history: fix, find and substitute |
fc num fc -s old=new str |
fc num none |
|||
command history: write to file, append to file, read from file |
history -w path history -a path history -r path |
fc -W path fc -A path fc -R path |
command history file
history expansion | |||||
---|---|---|---|---|---|
bash | fish | oh | tcsh | zsh | |
most recent command | !! | none | none | !! | !! |
n-th command | !n | none | none | !n | !n |
most recent command starting with str | !str | none | none | !str | !str |
most recent command with substitution | ^pattern^replacement | none | none | ^pattern^replacement | ^pattern^replacement |
nth command with substitution | !n:s/pattern/replacement/ | none | none | !n:s/pattern/replacement/ | !n:s/pattern/replacement/ |
n-th command with global substitution | !n:gs/pattern/replacement/ | none | none | !n:gs/pattern/replacement/ | !n:gs/pattern/replacement/ |
most recent arguments | !* | none | none | !* | |
first of most recent arguments | !:1 | none | none | !:1 | |
range of most recent arguments | !:n-m | none | none | !:n-m | |
last of most recent arguments | !$ | none | none | !$ | |
most recent command without arguments | !:0 | none | none | !:0 | |
m-th argument of n-th command | !n:m | none | none | !n:m |
history file | |||||
---|---|---|---|---|---|
bash | fish | oh | tcsh | zsh | |
location | HISTFILE=~/.bash_history | ~/.config/fish/fish_history | ~/.oh_history | set histfile ~/.tcsh_history | HISTFILE=~/.zsh_history |
memory size | HISTSIZE=2000 | 1000 | HISTSIZE=2000 | ||
file size | HISTFILESIZE=2000 | set savehist=2000 | SAVEHIST=2000 | ||
format | lines of input | ||||
timestamps | HISTTIMEFORMAT=%s | ||||
update time | on exit | on exit | |||
update method | appends to file; to only keep most recent dupe: HISTCONTROL=erasedups |
appends to file; to sort in memory file and most recent by timestamp and only keep the most recent, use: set savehist=2000 merge |
|||
ignore | HISTIGNORE=history:whoami |
Key Bindings
bash | fish | oh | tcsh | zsh | |
---|---|---|---|---|---|
list keybindings | bind -P | bind | bindkey | bindkey | |
list keymaps | help bind | none | none | bindkey -l | |
current keymap name | bind -V | grep keymap | none | none | ||
change keymap | bind 'set keymap emacs' | none | none | bindkey -A emacs main | |
list bindable functions | bind -l | bind -f | bindkey -l | ||
bind key to function | bind C-a:beginning-of-line | bind \ca beginning-of-line | |||
restore default binding for key |
Startup Files
bash | fish | oh | tcsh | zsh | |
---|---|---|---|---|---|
non-interactive shell startup files | $BASH_ENV | ~/.config/fish/config.fish | ~/.ohrc | /etc/csh.cshrc ~/.tcshrc ~/.cshrc |
/etc/zshenv $ZDOTDIR/.zshenv |
login shell startup files | /etc/profile ~/.bash_profile ~/.bash_login ~/.profile |
~/.config/fish/config.fish | ~/.ohrc | /etc/csh.login ~/.login |
non-interactive startup files /etc/zprofile $ZDOTDIR/.zprofile /etc/zshrc $ZDOTDIR/.zshrc /etc/zlogin $ZDOTDIR/.zlogin |
other interactive shell startup files | ~/.bashrc | ~/.config/fish/config.fish | ~/.ohrc | none | non-interactive startup files /etc/zshrc $ZDOTDIR/.zshrc |
login shell logout files | ~/.bash_logout | none | none | /etc/csh.logout ~/.logout |
$ZDOTDIR/.zlogout /etc/zlogout |
Prompt Customization
bash | fish | oh | tcsh | zsh | |
---|---|---|---|---|---|
set primary prompt | PS1='$ ' | function fish_prompt echo -n '$ ' end |
replace-make-prompt (method (suffix) { return "$ " }) |
set prompt='$ ' | PS1='$ ' |
set continued line prompt | PS2='> ' | none | none | set prompt2='> ' | PS2='> ' |
set select prompt | PS3='? ' | none | none | none | PS3='? ' |
set right prompt | none | function fish_right_prompt date end |
none | set rprompt='%Y-%W-%D %p' | RPS1='%D{%F %T}' |
set right continued line prompt | none | none | none | none | RSP2='...' |
dynamic information | |||||
working directory | none | pwd | %/ | %d %/ |
|
working directory with tilde abbrev | \w | abbreviate path components other than basename with single letter: prompt_pwd |
%~ | %~ | |
trailing components of working directory | %3C | %3d | |||
command number in history | \! | ! %! %h |
%! %h |
||
command number in session | \# | ||||
shell version | \v | ||||
shell level | $SHLVL | ||||
environment variable | $var | echo -n $var | %$var | $var | |
command substitution | $(cmd) | $(cmd) | |||
host name | \h \H |
%m %M |
|||
user | \u | %n | %n | ||
number of jobs | \j | %j | %j | ||
tty | %y | ||||
last command exit status | %? | %? | |||
conditional expression | |||||
shell privilege indicator | %# | ||||
continued line info | |||||
date and time | \D{strftime_format} | %D{strftime_format} | |||
text effects and escapes | |||||
escapes | \\ \[ \] | %% %{ %} | %% %{ %} | ||
bold | %B %b | %B %b | |||
underline | %U %u | %U %u | |||
standout | %S %s | %S %s | |||
foreground color | %F{red} %f | ||||
background color | %K{green} %k |