Check zshall for comprehensive description of Zsh features. Here's a Zsh guide.
Zsh has five data types: integer, float, scalar (a string), array and hash. Types are handled automatically with the exception of hashes which requires to declare a variable as a hash table using built-in typeset -A <variable name>.
typeset -Z 3 makes a variable at least three characters long padded with zeros if necessary.
typeset -Z 3 name
name=7
print $name
007typeset -r make a variable readonly.
typeset -r name
name=Bond
zsh: read-only variable: nametypeset -U create a unique set out of a list
typeset -U unique_set
unique_set=(1 1 1 2 2 3 3 1 2 3 3 5 4 4 4 5)
print $unique_set
1 2 3 5 4!!-> the previous command!str-> the most recent command starting withstr!?str[?]-> the most recent command containingstr
Quickies
Extract command's part
echo This is a very long command with many options and arguments
!:4-5
very long commandReplace command's part 1
echo This is a very long command with many options and arguments
!!:s/echo/cat
cat This is a very long command with many options and argumentsReplace command's part 2
less file.txt
^less^vim
vim file.txtCheck if variable exists
(( $+var )) && print “\tvar exists”
(( $+var )) || print “\tno, it doesn’t exist”Convert GIFs to JPGs
for i in **/*.gif; convert $i $i:r.jpgConvert PDFs to PNGs
for i in *.pdf; sips -s format png --rotate 270 --resampleHeight 1140 $i --out $i:r.pngCheck the entire filesystem to see if any executable files have been modified since yesterday
print -l /**/*(*.m-1)Remove spaces in the file name
for i in *.pdf; mv $i $i:gs/\ //Create files with range
touch file-99{01..05}.tmpArray
Assign content of /usr/bin to list
list=(/usr/bin/*)In zsh, arrays are indexed from 1 (instead of 0). Use a $# before the array name to get its size.
print $#listModifiers
Read about Zsh modifiers at man zshexpn.
Flags
str="hello, world!"
print -l ${(U)str} ${str:u} $str
HELLO, WORLD
HELLO, WORLD
hello, worldFiles
Find files that changed today
ls *(m0)Find Rakefile anywhere under current directory
ls **/RakefileList files bigger that 64mb
ls **/*(Lm+20)List transformation
list=(
/usr/bin/perl
/var/log/wtmp
/etc/inetd.conf
)-t -> similar to basename, it removes all leading pathname components, leaving the tail
print ${list:t}
perl wtmp inent.conf-h -> similar to dirname, it removes a trailing pathname component, leaving the head
print ${list:h}
/usr/bin /var/log /etcText search through elements of list, similar to grep
print ${(M)list:#/etc*}
/etc/inted.confInverted grep:
print ${list:#/etc*}
/usr/bin/perl /var/log/wtmpCombine modifiers
list=(/usr/bin/*)
print -l ${${(UM)list:#*ssh*}:t}
SSH
SSH-ADD
SSH-AGENT
SSH-KEYGEN
SSH-KEYSCANArrays can have both positive and negative numbers used as indexes. Positive numbers count forward from the start of the array; negative numbers count backward from the end of the array.
Retrieve sub-list
print $list[10,17]Hash
Declare a hash and assign key-value pairs to it
typeset -A hash
hash=(key value alice macos bob win10 jenny freebsd)print $hash
win10 freebsd value macosprint $hash[jenny]
freebsdAdd new element
hash[mike]=winxpprint $hash
win10 winxp freebsd value macosRemove element
unset hash[mike]Scripting
Bourne shell scripts are usually difficult to write in a portable way, because they often rely on external programs to do data transformation, zsh on the other hand has the capabilities of many traditional Unix programs built into it. In order to keep Zsh scripts as portable as possible you should always use its built-in features.
ZMV
zmv moves (or renames) files based on the pattern. Its manual is in the zshcontrib man page. zmv must be loaded with autoload zmv to be available.
Use -n to perform a dry run with zmv.
zmv '* *' '$f:gs/ /_’zmv '*.(*).(*).([0-9][0-9])*.mkv' '$1_$2-$3.mkv'i=0; zmv -n '*' 'file_${(l:3::0:)$((++i))}'
mv -- '2013-04-28 15.55.50.jpg' file_001
mv -- '2013-11-20 10.56.35.jpg' file_002
mv -- '2014-04-23 11.14.18.jpg' file_003