Bash cheatsheet
Cheatsheets
$(< file) # Тоже что $(cat file) |& # На ввод следующей команде попадет как stdout так и stderr expr ? expr : expr условие ? выраж1 : выраж2 # Условный оператор в форме тернарного. Если условие истинно, тогда выполниться выраж1 в противном случае выраж2
Variables
NAME="John" echo $NAME echo "$NAME" echo "${NAME}"
String quotes
NAME="John" echo "Hi $NAME" #=> Hi John echo 'Hi $NAME' #=> Hi $NAME
Shell execution
echo "I'm in $(pwd)" echo "I'm in `pwd`"
Conditional execution
git commit && git push # AND git commit || echo "Commit failed" # OR
Functions
get_name() { echo "John" } echo "You are $(get_name)"
Conditionals
if [[ -z "$string" ]]; then echo "String is empty" elif [[ -n "$string" ]]; then echo "String is not empty" fi -a file # True if file exists. -b file # True if file exists and is a block special file. -c file # True if file exists and is a character special file. -d file # True if file exists and is a directory. -e file # True if file exists. -f file # True if file exists and is a regular file. -g file # True if file exists and its set-group-id bit is set. -h file # True if file exists and is a symbolic link. -k file # True if file exists and its "sticky" bit is set. -p file # True if file exists and is a named pipe (FIFO). -r file # True if file exists and is readable. -s file # True if file exists and has a size greater than zero. -t fd # True if file descriptor fd is open and refers to a terminal. -u file # True if file exists and its set-user-id bit is set. -w file # True if file exists and is writable. -x file # True if file exists and is executable. -G file # True if file exists and is owned by the effective group id. -L file # True if file exists and is a symbolic link. -N file # True if file exists and has been modified since it was last read. -O file # True if file exists and is owned by the effective user id. -S file # True if file exists and is a socket. file1 -ef file2 # True if file1 and file2 refer to the same device and inode numbers. file1 -nt file2 # True if file1 is newer (according to modification date) than file2, or if file1 exists and file2 does not. file1 -ot file2 # True if file1 is older than file2, or if file2 exists and file1 does not. -o optname # True if the shell option optname is enabled. The list of options appears in the description of the -o option to the set builtin (see The Set Builtin). -v varname # True if the shell variable varname is set (has been assigned a value). -R varname # True if the shell variable varname is set and is a name reference. -z string # True if the length of string is zero. -n string # True if the length of string is non-zero. string1 == string2 string1 = string2 # True if the strings are equal. ‘=’ should be used with the test command for POSIX conformance. string1 != string2 # True if the strings are not equal. string1 < string2 # True if string1 sorts before string2 lexicographically. string1 > string2 # True if string1 sorts after string2 lexicographically. arg1 OP arg2 # OP is one of ‘-eq’, ‘-ne’, ‘-lt’, ‘-le’, ‘-gt’, or ‘-ge’. These arithmetic binary operators return true if arg1 is equal to, not equal to, less than, less than or equal to, greater than, or greater than or equal to arg2, respectively. Arg1 and arg2 may be positive or negative integers. When used with the [[ command, Arg1 and Arg2 are evaluated as arithmetic expressions
Strict mode
set -euo pipefail IFS=#39;\n\t'
Brace expansion
echo {A,B}.js {A,B} # Same as A B {A,B}.js # Same as A.js B.js {1..5} # Same as 1 2 3 4 5 {0..10..2} # Same as 0 2 4 6 8 10
Parameter expansions
Basics
name="John" echo ${name} echo ${name/J/j} #=> "john" (substitution) echo ${name:0:2} #=> "Jo" (slicing) echo ${name::2} #=> "Jo" (slicing) echo ${name::-1} #=> "Joh" (slicing) echo ${name:(-1)} #=> "n" (slicing from right) echo ${name:(-2):1} #=> "h" (slicing from right) echo ${food:-Cake} #=> $food or "Cake" length=2 echo ${name:0:length} #=> "Jo" STR="/path/to/foo.cpp" echo ${STR%.cpp} # /path/to/foo echo ${STR%.cpp}.o # /path/to/foo.o echo ${STR##*.} # cpp (extension) echo ${STR##*/} # foo.cpp (basepath) echo ${STR#*/} # path/to/foo.cpp echo ${STR##*/} # foo.cpp echo ${STR/foo/bar} # /path/to/bar.cpp STR="Hello world" echo ${STR:6:5} # "world" echo ${STR:-5:5} # "world" SRC="/path/to/foo.cpp" BASE=${SRC##*/} #=> "foo.cpp" (basepath) DIR=${SRC%$BASE} #=> "/path/to/" (dirpath)
Substitution
${FOO%suffix} # Remove suffix ${FOO#prefix} # Remove prefix ${FOO%%suffix} # Remove long suffix ${FOO##prefix} # Remove long prefix ${FOO/from/to} # Replace first match ${FOO//from/to} # Replace all ${FOO/%from/to} # Replace suffix ${FOO/#from/to} # Replace prefix
Comments
# Single line comment : ' This is a multi line comment '
Substrings
${FOO:0:3} # Substring (position, length) ${FOO:-3:3} # Substring from the right
Length
${#FOO} Length of $FOO
Manipulation
STR="HELLO WORLD!" echo ${STR,} #=> "hELLO WORLD!" (lowercase 1st letter) echo ${STR,,} #=> "hello world!" (all lowercase) STR="hello world!" echo ${STR^} #=> "Hello world!" (uppercase 1st letter) echo ${STR^^} #=> "HELLO WORLD!" (all uppercase)
Default values
${FOO:-val} # $FOO, or val if not set ${FOO:=val} # Set $FOO to val if not set ${FOO:+val} # val if $FOO is set ${FOO:?message} # Show error message and exit if $FOO is not set # The : is optional (eg, ${FOO=word} works)
Loops
# Basic for loop for i in /etc/rc.*; do echo $i done # C-like for loop for ((i = 0 ; i < 100 ; i++)); do echo $i done # Ranges for i in {1..5}; do echo "Welcome $i" done # With step size for i in {5..50..5}; do echo "Welcome $i" done # Reading lines < file.txt | while read line; do echo $line done # Forever while true; do ··· done
Functions
# Defining functions myfunc() { echo "hello $1" } # Same as above (alternate syntax) function myfunc() { echo "hello $1" } myfunc "John" # Returning values myfunc() { local myresult='some value' echo $myresult } result="$(myfunc)" # Raising errors myfunc() { return 1 } if myfunc; then echo "success" else echo "failure" fi
Arguments
$# # Number of arguments $* # All arguments $@ # All arguments, starting from first $1 # First argument
Conditionals
Conditions
Note that [[ is actually a command/program that returns either 0 (true) or 1 (false). Any program that obeys the same logic (like all base utils, such as grep(1) or ping(1)) can be used as condition, see examples. [[ -z STRING ]] # Empty string [[ -n STRING ]] # Not empty string [[ STRING == STRING ]] # Equal [[ STRING != STRING ]] # Not Equal [[ NUM -eq NUM ]] # Equal [[ NUM -ne NUM ]] # Not equal [[ NUM -lt NUM ]] # Less than [[ NUM -le NUM ]] # Less than or equal [[ NUM -gt NUM ]] # Greater than [[ NUM -ge NUM ]] # Greater than or equal [[ STRING =~ STRING ]] # Regexp (( NUM < NUM )) # Numeric conditions [[ -o noclobber ]] # If OPTIONNAME is enabled [[ ! EXPR ]] # Not [[ X ]] && [[ Y ]] # And [[ X ]] || [[ Y ]] # Or # File conditions [[ -e FILE ]] # Exists [[ -r FILE ]] # Readable [[ -h FILE ]] # Symlink [[ -d FILE ]] # Directory [[ -w FILE ]] # Writable [[ -s FILE ]] # Size is > 0 bytes [[ -f FILE ]] # File [[ -x FILE ]] # Executable [[ FILE1 -nt FILE2 ]] # 1 is more recent than 2 [[ FILE1 -ot FILE2 ]] # 2 is more recent than 1 [[ FILE1 -ef FILE2 ]] # Same files
Example
if ping -c 1 google.com; then echo "It appears you have a working internet connection" fi if grep -q 'foo' ~/.bash_history; then echo "You appear to have typed 'foo' in the past" fi # String if [[ -z "$string" ]]; then echo "String is empty" elif [[ -n "$string" ]]; then echo "String is not empty" fi # Combinations if [[ X ]] && [[ Y ]]; then ... fi # Equal if [[ "$A" == "$B" ]] # Regex if [[ "A" =~ "." ]] if (( $a < $b )); then echo "$a is smaller than $b" fi if [[ -e "file.txt" ]]; then echo "file exists" fi
Arrays
# Defining arrays Fruits=('Apple' 'Banana' 'Orange') Fruits[0]="Apple" Fruits[1]="Banana" Fruits[2]="Orange" # Working with arrays echo ${Fruits[0]} # Element #0 echo ${Fruits[@]} # All elements, space-separated echo ${#Fruits[@]} # Number of elements echo ${#Fruits} # String length of the 1st element echo ${#Fruits[3]} # String length of the Nth element echo ${Fruits[@]:3:2} # Range (from position 3, length 2) # Operations Fruits=("${Fruits[@]}" "Watermelon") # Add Fruits+=('Watermelon') # Also add Fruits=( ${Fruits[@]/Ap*/} ) # Remove by regex match unset Fruits[2] # Remove one item Fruits=("${Fruits[@]}") # Duplicate Fruits=("${Fruits[@]}" "${Veggies[@]}") # Concatenate lines=(`cat "logfile"`) # Read from file # Iteration for i in "${arrayName[@]}"; do echo $i done
Dictionaries
# Defining declare -A sounds sounds[dog]="bark" sounds[cow]="moo" sounds[bird]="tweet" sounds[wolf]="howl" # Declares sound as a Dictionary object (aka associative array). # Working with dictionaries echo ${sounds[dog]} # Dog's sound echo ${sounds[@]} # All values echo ${!sounds[@]} # All keys echo ${#sounds[@]} # Number of elements unset sounds[dog] # Delete dog
Iteration
# Iterate over values for val in "${sounds[@]}"; do echo $val done # Iterate over keys for key in "${!sounds[@]}"; do echo $key done
Options
# Options set -o noclobber # Avoid overlay files (echo "hi" > foo) set -o errexit # Used to exit upon error, avoiding cascading errors set -o pipefail # Unveils hidden failures set -o nounset # Exposes unset variables # Glob options set -o nullglob # Non-matching globs are removed ('*.foo' => '') set -o failglob # Non-matching globs throw errors set -o nocaseglob # Case insensitive globs set -o globdots # Wildcards match dotfiles ("*.sh" => ".foo.sh") set -o globstar # Allow ** for recursive matches ('lib/**/*.rb' => 'lib/a/b/c.rb') # Set GLOBIGNORE as a colon-separated list of patterns to be removed from glob matches.
History
# Commands history # Show history shopt -s histverify # Don’t execute expanded result immediately # Expansions !$ # Expand last parameter of most recent command !* # Expand all parameters of most recent command !-n # Expand nth most recent command !n # Expand nth command in history !<command> # Expand most recent invocation of command <command> # Operations !! # Execute last command again !!:s/<FROM>/<TO>/ # Replace first occurrence of <FROM> to <TO> in most recent command !!:gs/<FROM>/<TO>/ # Replace all occurrences of <FROM> to <TO> in most recent command !$:t # Expand only basename from last parameter of most recent command !$:h # Expand only directory from last parameter of most recent command !! and !$ # can be replaced with any valid expansion. # Slices !!:n # Expand only nth token from most recent command (command is 0; first argument is 1) !^ # Expand first argument from most recent command !$ # Expand last token from most recent command !!:n-m # Expand range of tokens from most recent command !!:n-$ # Expand nth token to last from most recent command !! # can be replaced with any valid expansion i.e. !cat, !-2, !42, etc.
Miscellaneous
# Numeric calculations $((a + 200)) # Add 200 to $a $((RANDOM%=200)) # Random number 0..200 # Subshells (cd somedir; echo "I'm now in $PWD") pwd # still in first directory # Redirection python hello.py > output.txt # stdout to (file) python hello.py >> output.txt # stdout to (file), append python hello.py 2> error.log # stderr to (file) python hello.py 2>&1 # stderr to stdout python hello.py 2>/dev/null # stderr to (null) python hello.py &>/dev/null # stdout and stderr to (null) python hello.py < foo.txt # feed foo.txt to stdin for python # Inspecting commands command -V cd #=> "cd is a function/alias/whatever" # Trap errors trap 'echo Error at about $LINENO' ERR or traperr() { echo "ERROR: ${BASH_SOURCE[1]} at about ${BASH_LINENO[0]}" } set -o errtrace trap traperr ERR # Case/switch case "$1" in start | up) vagrant up ;; *) echo "Usage: $0 {start|stop|ssh}" ;; esac # Source relative source "${0%/*}/../share/foo.sh" printf printf "Hello %s, I'm %s" Sven Olga #=> "Hello Sven, I'm Olga printf "1 + 1 = %d" 2 #=> "1 + 1 = 2" printf "This is how you print a float: %f" 2 #=> "This is how you print a float: 2.000000" # Directory of script DIR="${0%/*}" # Getting options while [[ "$1" =~ ^- && ! "$1" == "--" ]]; do case $1 in -V | --version ) echo $version exit ;; -s | --string ) shift; string=$1 ;; -f | --flag ) flag=1 ;; esac; shift; done if [[ "$1" == '--' ]]; then shift; fi # Heredoc cat <<END hello world END # Reading input echo -n "Proceed? [y/n]: " read ans echo $ans read -n 1 ans # Just one character # Special variables $? # Exit status of last task $! # PID of last background task $ # PID of shell $0 # Filename of the shell script # Go to previous directory pwd # /home/user/foo cd bar/ pwd # /home/user/foo/bar cd - pwd # /home/user/foo
HOTKEYS
Ctrl + a
– перейти на начало командной строки
Ctrl + e
– перейти в конец командной строки
Ctrl + k
– удалить от курсора до конца командной строки
Ctrl + u
– удалить от курсора до начала командной строки
Ctrl + w
– удалить от курсора до начала слова
Ctrl + y
– вставить слово или текст который был вырезано с использованием одного из подходящих сочетаний клавиш
Ctrl + xx
– переместиться между началом командной строки и текущим положением курсора (работает в обе стороны)
Alt + b
– переместить курсор на одно слово назад (или переместиться на начало текущего слова)
Alt + f
– переместиться вперед на одно слово (или к началу текущего слова)
Alt + d
– удалить до конца слова начиная с текущего положения курсора (все слово, если курсор находится в его начале)
Alt + c
– сделать букву заглавной и переместиться в конец слова
Alt + u
– сделать все буквы большими до конца слова
Alt + l
– сделать все буквы маленькими до конца слова
Alt + t
– поменять местами текущее слово и предыдущее
Ctrl + f
– переместиться вперед на один символ
Ctrl + b
– переместиться назад на один символ
Ctrl + d
– удалить символ под курсором
Ctrl + h
– удалить символ перед курсором
Ctrl + t
– поменять местами символ под курсором и предыдущий.
Ctrl + r
– искать в истории команд
Ctrl + g
– выйти из режима поиска команд
Ctrl + p
– перейти к предыдущей команде в истории
Ctrl + n
– перейти к следующей команде в истории
Alt + .
– использовать последнее слово из предыдущей команды.
Управление работой команд bash
Ctrl + s
– остановить вывод на экран (для долго выполняющихся команд с расширенным выводом)
Ctrl + q
– продолжить вывод на экран
Ctrl + c
– остановить работу команды
Ctrl + z
– приостановить работу команды.
Команды с восклицательным знаком (Bash Bang)
!!
– выполнить предыдущую команду
!blah
– выполнить последнюю команду начинающуюся с blah (к примеру, !ls)
!blah:p
– вывести в консоль текст команды, которую бы выполнила команда !blah(также добавить эту команду в конец истории)
!$
– последнее слово предыдущей команды (то же самое, что и Alt + .)
!$:p
– вывести в консоль текст, который бы заменила команда !$
!*
– предыдущая команда за исключением первого слова (к примеру, если предыдущая команда была vi cd /etc, то !* выполнит cd /etc)
!*:p
– вывести в консоль текс, который бы заменила команда !*.
С помощью символов ^^ мы можем выполнить предыдущую команду с заменой части текста на другой. К примеру:
ps a ^a^aux ls aux
Таким образом содержимое между "крышечками" заменяется на содержимое, которое указано после них.