1ZSH-LOVERS(1)                                                    ZSH-LOVERS(1)
2
3
4

NAME

6       zsh-lovers - tips, tricks and examples for the Z shell
7

SYNOPSIS

9       Just read it. ;-)
10

OVERVIEW

12       Whenever we look at the zsh manual we wonder why there are no examples
13       or those simply things in (shell) life. The zsh contains many features,
14       but there was no manpage with some examples (like procmailex(5)).
15       That’s why we wrote this manpage.
16
17       Most of the tricks and oneliner come from the mailinglists zsh-users,
18       zsh-workers, google, newsgroups and from ourself. See section LINKS for
19       details.
20
21       Note: This manpage (zsh-lovers(1)) is not an official part of the Z
22       shell! It’s just a just for fun - manpage ;) For comments, bugreports
23       and feedback take a quick look at the section BUGS.
24

SHELL-SCRIPTING

26       This section provides some examples for often needed shellscript-stuff.
27       Notice that you should not use otherwise most examples won’t work.
28       Parse options in shellscripts. Example taken from ZWS by Adam
29       Chodorowski (http://www.chodorowski.com/projects/zws/):
30
31           parse_options()
32           {
33               o_port=(-p 9999)
34               o_root=(-r WWW)
35               o_log=(-d ZWS.log)
36
37               zparseopts -K -- p:=o_port r:=o_root l:=o_log h=o_help
38               if [[ $? != 0 || "$o_help" != "" ]]; then
39                   echo Usage: $(basename "$0") "[-p PORT] [-r DIRECTORY]"
40                   exit 1
41               fi
42
43               port=$o_port[2]
44               root=$o_root[2]
45               log=$o_log[2]
46
47               if [[ $root[1] != '/' ]]; then root="$PWD/$root"; fi
48           }
49           # now use the function:
50           parse_options $*
51

EXAMPLES

53       Available subsections are Aliases, Completion, Unsorted/Misc examples,
54       (Recursive) Globbing - Examples, Modifiers usage, Redirection-Examples,
55       ZMV-Examples and Module-Examples.
56
57   ALIASES
58       Suffix aliases are supported in zsh since version 4.2.0. Some examples:
59
60           alias -s tex=vim
61           alias -s html=w3m
62           alias -s org=w3m
63
64       Now pressing return-key after entering foobar.tex starts vim with
65       foobar.tex. Calling a html-file runs browser w3m. www.zsh.org and
66       pressing enter starts w3m with argument www.zsh.org. Global aliases can
67       be used anywhere in the command line. Example:
68
69           $ alias -g C='| wc -l'
70           $ grep alias ~/.zsh/* C
71           443
72
73       Some more or less useful global aliases (choose whether they are useful
74       or not for you on your own):
75
76           alias -g ...='../..'
77           alias -g ....='../../..'
78           alias -g .....='../../../..'
79           alias -g CA="2>&1 | cat -A"
80           alias -g C='| wc -l'
81           alias -g D="DISPLAY=:0.0"
82           alias -g DN=/dev/null
83           alias -g ED="export DISPLAY=:0.0"
84           alias -g EG='|& egrep'
85           alias -g EH='|& head'
86           alias -g EL='|& less'
87           alias -g ELS='|& less -S'
88           alias -g ETL='|& tail -20'
89           alias -g ET='|& tail'
90           alias -g F=' | fmt -'
91           alias -g G='| egrep'
92           alias -g H='| head'
93           alias -g HL='|& head -20'
94           alias -g Sk="*~(*.bz2|*.gz|*.tgz|*.zip|*.z)"
95           alias -g LL="2>&1 | less"
96           alias -g L="| less"
97           alias -g LS='| less -S'
98           alias -g MM='| most'
99           alias -g M='| more'
100           alias -g NE="2> /dev/null"
101           alias -g NS='| sort -n'
102           alias -g NUL="> /dev/null 2>&1"
103           alias -g PIPE='|'
104           alias -g R=' > /c/aaa/tee.txt '
105           alias -g RNS='| sort -nr'
106           alias -g S='| sort'
107           alias -g TL='| tail -20'
108           alias -g T='| tail'
109           alias -g US='| sort -u'
110           alias -g VM=/var/log/messages
111           alias -g X0G='| xargs -0 egrep'
112           alias -g X0='| xargs -0'
113           alias -g XG='| xargs egrep'
114           alias -g X='| xargs'
115
116   COMPLETION
117       See also man 1 zshcompctl zshcompsys zshcompwid. zshcompctl is the old
118       style of zsh programmable completion, zshcompsys is the new completion
119       system, zshcompwid are the zsh completion widgets.
120
121       Some functions, like _apt and _dpkg, are very slow. You can use a cache
122       in order to proxy the list of results (like the list of available
123       debian packages) Use a cache:
124
125           zstyle ':completion:*' use-cache on
126           zstyle ':completion:*' cache-path ~/.zsh/cache
127
128       Prevent CVS files/directories from being completed:
129
130           zstyle ':completion:*:(all-|)files' ignored-patterns '(|*/)CVS'
131           zstyle ':completion:*:cd:*' ignored-patterns '(*/)#CVS'
132
133       Fuzzy matching of completions for when you mistype them:
134
135           zstyle ':completion:*' completer _complete _match _approximate
136           zstyle ':completion:*:match:*' original only
137           zstyle ':completion:*:approximate:*' max-errors 1 numeric
138
139       And if you want the number of errors allowed by _approximate to
140       increase with the length of what you have typed so far:
141
142           zstyle -e ':completion:*:approximate:*' \
143                   max-errors 'reply=($((($#PREFIX+$#SUFFIX)/3))numeric)'
144
145       Ignore completion functions for commands you don’t have:
146
147           zstyle ':completion:*:functions' ignored-patterns '_*'
148
149       With helper functions like:
150
151           xdvi() { command xdvi ${*:-*.dvi(om[1])} }
152
153       you can avoid having to complete at all in many cases, but if you do,
154       you might want to fall into menu selection immediately and to have the
155       words sorted by time:
156
157           zstyle ':completion:*:*:xdvi:*' menu yes select
158           zstyle ':completion:*:*:xdvi:*' file-sort time
159
160       Completing process IDs with menu selection:
161
162           zstyle ':completion:*:*:kill:*' menu yes select
163           zstyle ':completion:*:kill:*'   force-list always
164
165       If you end up using a directory as argument, this will remove the
166       trailing slash (useful in ln)
167
168           zstyle ':completion:*' squeeze-slashes true
169
170       cd will never select the parent directory (e.g.: cd ../<TAB>):
171
172           zstyle ':completion:*:cd:*' ignore-parents parent pwd
173
174       Another method for quick change directories. Add this to your ~/.zshrc,
175       then just enter “cd ..../dir”
176
177           rationalise-dot() {
178             if [[ $LBUFFER = *.. ]]; then
179               LBUFFER+=/..
180             else
181               LBUFFER+=.
182             fi
183           }
184           zle -N rationalise-dot
185           bindkey . rationalise-dot
186
187   UNSORTED/MISC examples
188       Hint: A list of valid glob Qualifiers can be found in zshexpn(1). See
189       “man 1 zshexpn | less -p” Qualifiers for details.
190
191           # Get the names of all files that *don't* match a pattern *anywhere* on the
192           # file (and without ``-L'' because its GNUish)
193             $ print -rl -- *(.^e{'grep -q pattern $REPLY'})
194             # or
195             $ : *(.e{'grep -q pattern $REPLY || print -r -- $REPLY'})
196
197           # random numbers
198             $ echo $[${RANDOM}%1000]     # random between 0-999
199             $ echo $[${RANDOM}%11+10]    # random between 10-20
200             $ echo ${(l:3::0:)${RANDOM}} # N digits long (3 digits)
201
202           # reverse a word
203             $ echo "${(j::)${(@Oa)${(s::):-hello}}}"
204
205           # Show newest directory
206             $ ls -ld *(/om[1])
207
208           # random array element
209             $ FILES=( .../files/* )
210             $ feh $FILES[$RANDOM%$#FILES+1]
211
212           # cat first line in all files in this dir
213             $ for file (*(ND-.)) IFS= read -re < $file
214
215           # test if a parameter is numeric
216             $ if [[ $1 == <-> ]] ; then
217                    echo numeric
218               else
219                    echo non-numeric
220               fi
221
222           # Show me all the .c files for which there doesn't exist a .o file.
223             $ print *.c(e_'[[ ! -e $REPLY:r.o ]]'_)
224
225           # All files in /var/ that are not owned by root
226             $ ls -ld /var/*(^u:root)
227
228           # All files for which the owner hat read and execute permissions
229             $ echo *(f:u+rx:)
230
231           # The same, but also others don't have execute permissions
232             $ echo *(f:u+rx,o-x:)
233
234           # brace expansion - example
235             $ X=(A B C)
236             $ Y=(+ -)
237             $ print -r -- $^X.$^Y
238             A.+ A.- B.+ B.- C.+ C.-
239
240           # Fetch the newest file containing the string 'fgractg*.log' in the
241           # filename and contains the string 'ORA-' in it
242             $ file=(fgractg*.log(Nm0om[1]))
243             $ (($#file)) && grep -l ORA- $file
244             # without Zsh
245             $ files=$( find . -name . -o -prune -name 'fgractg*>log' -mtime 0 -print )
246             > if [ -n "$files" ]; then
247             >    IFS='
248             > '
249             > set -f
250             > file=$(ls -td $files | head -1)
251             > grep -l ORA- "$file"
252             > fi
253
254           # keep specified number of child processes running until entire task finished
255             $ zsh -c 'sleep 1 & sleep 3 & sleep 2& print -rl -- $jobtexts'
256
257           # Remove zero length and .bak files in a directory
258             $ rm -i *(.L0) *.bak(.)
259
260           # print out files that don't have extensions
261             $ printf '%s\n' ^?*.*
262             $ printf '%s\n' ^?*.[^.]*(D)
263             $ ls -d -- ^?*.*(D)
264
265           # Finding files which does not contain a specific string
266             $ print -rl file* | comm -2 -3 - <(grep -l string file*)'
267             $ for f (file*(N)) grep -q string $f || print -r $f'
268
269           # Show/Check whether a option is set or not. It works both with $options as
270           # with $builtins
271             $ echo $options[correct]
272             off
273             $ $options[zle]
274             on
275
276           # Count the number of directories on the stack
277             $ print $((${${(z)${(f)"$(dirs -v)"}[-1]}[1]} + 1)) # or
278             $ dirs -v | awk '{n=$1}END{print n+1}'
279
280           # Matching all files which do not have a dot in filename
281             $ ls *~*.*(.)
282
283           # Show only the ip-address from ``ifconfig device''
284             # ifconfig from net-tools (Linux)
285             $ print ${${$(LC_ALL=C /sbin/ifconfig eth0)[7]}:gs/addr://}
286             # ifconfig from 4.2BSD {Free,Net,Open}BSD
287             $ print ${$(/sbin/ifconfig tun0)[6]}
288
289           # Ping all the IP addresses in a couple of class C's or all hosts
290           # into /etc/hosts
291             $ for i in {1..254}; do ping -c 1 192.168.13.$i; done
292             or
293             $ I=1
294             $ while ( [[ $I -le 255 ]] ) ; do ping -1 2 150.150.150.$I; let I++; done
295             or
296             $ for i in $(sed 's/#.*//' > /etc/hosts | awk '{print $2}')
297             : do
298             :    echo "Trying $i ... "
299             :    ping -c 1 $i ;
300             :    echo '============================='
301             : done
302
303           # load all available modules at startup
304             $ typeset -U m
305             $ m=()
306             $ for md ($module_path) m=($m $md/**/*(*e:'REPLY=${REPLY#$md/}'::r))
307             $ zmodload -i $m
308
309           # Rename all files within a directory such that their names get a numeral
310           # prefix in the default sort order.
311             $ i=1; for j in *; do mv $j $i.$j; ((i++)); done
312             $ i=1; for f in *; do mv $f $(echo $i | \
313               awk '{ printf("%03d", $0)}').$f; ((i++)); done
314             $ integer i=0; for f in *; do mv $f $[i+=1].$f; done
315
316           # Find (and print) all symbolic links without a target within the current
317           # dirtree.
318             $ $ file **/*(D@) | fgrep broken
319             $ for i in **/*(D@); [[ -f $i || -d $i ]] || echo $i
320             $ echo **/*(@-^./=%p)
321             $ print -l **/*(-@)
322
323           # List all plain files that do not have extensions listed in `fignore'
324             $ ls **/*~*(${~${(j/|/)fignore}})(.)
325             # see above, but now omit executables
326             $ ls **/*~*(${~${(j/|/)fignore}})(.^*)
327
328           # Print out files that don't have extensions (require *setopt extendedglob*
329           # and *setopt dotglob*)
330             $ printf '%s\n' ^?*.*
331
332           # List files in reverse order sorted by name
333             $ print -rl -- *(On)
334             or
335             $ print -rl -- *(^on)
336
337           # Synonymic to ``ps ax | awk '{print $1}'''
338             $ print -l /proc/*/cwd(:h:t:s/self//)
339
340           # Get the PID of a process (without ``ps'', ``sed'', ``pgrep'', ..
341           # (under Linux)
342             $ pid2 () {
343             >   local i
344             >   for i in /proc/<->/stat
345             > do
346             >   [[ "$(< $i)" = *\((${(j:|:)~@})\)* ]] && echo $i:h:t
347             > done
348             > }
349
350           # for X in 'n' 'o' 'p' 'q' 'r' 's' 't' 'u' 'v' 'w' 'x' 'y'; do ...
351             $ for (( i = 36#n; i <= 36#y; i++ )); do
352             >   print ${$(([##36]i)):l}
353             > done
354           # or in combination with ``dc''
355             $ print {$((##n))..$((##y))}P\ 10P | dc
356           # or with ``eval''
357             $ eval print '${$(([##36]'{$((36#n))..$((36#y))}')):l}'
358
359           # foreach in one line of shell
360             $ for f (*) print -r -- $f
361
362           # copy a directory recursively without data/files
363             $ dirs=(**/*(/))
364             $ cd -- $dest_root
365             $ mkdir -p -- $dirs
366           # or without zsh
367             $ find . -type d -exec env d="$dest_root" \
368               sh -c ' exec mkdir -p -- "$d/$1"' '{}' '{}' \;
369
370           # If `foo=23'', then print with 10 digit with leading '0'.
371             $ foo=23
372             $ print ${(r:10::0:)foo}
373
374           # find the name of all the files in their home directory that have
375           # 20 or more characters in their file names
376             print -rl $HOME/${(l:20::?:)~:-}*
377
378           # Save arrays
379             $ print -r -- ${(qq)m} > $nameoffile      # save it
380             $ eval "m=($(cat -- $nameoffile)"            # or use
381             $ m=("${(@Q)${(z)"$(cat -- $nameoffile)"}}") # to restore it
382
383           # get a "ls -l" on all the files in the tree that are younger than a
384           # specified age (e.g "ls -l" all the files in the tree that where
385           # modified in the last 2 days)
386             $ ls -tld **/*(m-2)
387           # This will give you a listing 1 file perl line (not à la ls -R).
388           # Think of an easy way to have a "ls -R" style output with
389           # only files newer than 2 day old.
390             $ for d (. ./**/*(/)) {
391             >   print -r -- $'\n'${d}:
392             >   cd $d && {
393             >       l=(*(Nm-2))
394             >       (($#l)) && ls -ltd -- $l
395             >       cd ~-
396             >   }
397             > }
398           # If you also want directories to be included even if their mtime
399           # is more than 2 days old:
400             $ for d (. ./**/*(/)) {
401             >   print -r -- $'\n'${d}:
402             >   cd $d && {
403             >      l=(*(N/,m-2))
404             >      (($#l)) && ls -ltd -- $l
405             >      cd ~-
406             >   }
407             > }
408           # And if you want only the directories with mtime < 2 days to be listed:
409             $ for d (. ./**/*(N/m-2)) {
410             >   print -r -- $'\n'${d}:
411             >   cd $d && {
412             >      l=(*(Nm-2))
413             >      (($#l)) && ls -ltd -- $l
414             >      cd ~-
415             >   }
416             > }
417
418           # print 42 ``-''
419             $ echo ${(l:42::-:)}
420           # or use ``$COLUMS''
421             $ echo ${(l:$COLUMNS::-:)}
422           # and now with colors (require autoload colors ;colors)
423             $ echo "$bg[red]$fg[black]${(l:42::-:)}"
424
425           # Redirect STDERR to a command like xless without redirecting STDOUT as well.
426             $ foo 2>>(xless)
427           # but this executes the command asynchronously. To do it synchronously:
428             $ { { foo 1>&3 } 2>&1 | xless } 3>&1
429
430           # Rename all MP3-Files from name with spaces.mp3 to Name With Spaces.mp3
431             $ for i in *.mp3; do
432             >     mv $i ${${(C)i}:s/Mp3/mp3/}
433             > done
434
435           # Match file names containing only digits and ending with .xml (require
436           # *setopt kshglob*)
437             $ ls -l [0-9]##.xml
438             $ ls -l <0->.xml
439
440           # Remove all "non txt" files
441             $ rm ./^*.txt
442
443           # Move 200 files from a directory into another
444             $ mv -- *([1,200]) /another/Dir
445
446           # Convert images (foo.gif => foo.png):
447             $ for i in **/*.gif; convert $i $i:r.png
448
449           # convert a collection of mp3 files to wave or cdr,
450           # e.g. file.wav -> file.mp3)
451             $ for i (./*.mp3){mpg321 --w - $i > ${i:r}.wav}
452
453           # Download with LaTeX2HTML  created Files (for example the ZSH-Guide):
454             $ for f in https://zsh.sourceforge.io/Guide/zshguide{,{01..08}}.html; do
455             >     lynx -source $f >${f:t}
456             > done
457
458           # Move all files in dir1 and dir2 that have line counts greater than 10 to
459           # another directory say "/more10"
460             $ mv dir[12]/**/*.cr(-.e{'((`wc -l < $REPLY` > 10))'}) /more10
461
462           # Make with dpkg a master-list of everyfile that it has installed
463             $ diff <(find / | sort) <(cat /var/lib/dpkg/info/*.list | sort)
464
465           # Replace this fucking Escape-Sequences:
466             $ autoload colors ; colors
467             $ print "$bg[cyan]$fg[blue]You are a idiot" >> /dev/pts/3
468
469           # Get ASCII value of a character
470             $ char=N ; print $((#char))
471
472           # Filename "Erweiterung"
473           # Note: The (N) says to use the nullglob option for this particular
474           # glob pattern.
475             $ for i in *.o(N); do
476             >     rm $i
477             > done
478
479           # Rename files; i. e. FOO to foo and bar to BAR
480             $ for i in *(.); mv $i ${i:l} # `FOO' to `foo'
481             $ for i in *(.); mv $i ${i:u} # `bar to `BAR'
482
483           # Show all suid-files in $PATH
484             $ ls -latg ${(s.:.)PATH} | grep '^...s'
485           # or more complex ;)
486             $ print -l ${^path}/*(Ns,S)
487           # or show only executables with a user given pattern
488             $ print -l ${^path}/*vim*(*N)
489
490           # gzip files when containing a certain string
491             $ gzip ${(ps:\0:)"$(grep -lZ foobar ./*.txt(.))"}
492
493           # A small  one-liner, that reads from stdin and prints to stdout the first
494           # unique line i. e. does not print lines that have been printed before
495           # (this is similar to the unique command, but unique can only handle
496           # adjacent lines).
497             $ IFS=$'\n\n'; print -rl -- ${(Oau)${(Oa)$(cat file;echo .)[1,-2]}}
498
499           # Lists every executable in PATH
500             $ print -l ${^path}/*(-*N)
501
502           # Match all .c files in all subdirectories, _except_ any SCCS subdirectories?
503             $ ls **/*.c~(*/)#SCCS/*
504
505           # List all `README' - files case-insensitive with max. one typo
506             $ ls **/*(#ia2)readme
507
508           # case insensitive checking for variables
509             $ if [[ $OSTYPE == (#i)LINUX*(#I) ]]; then
510             >    echo "Penguin on board."
511             > else
512             >    echo "Not a Linux."
513             > fi
514
515   (Recursive) Globbing - Examples
516       A list of valid glob Qualifiers can be found in zshexpn(1). Note: **/
517       is equivalent to (*/)#! For example:
518
519           $ print (*/)#zsh_us.ps
520           zsh-4.2.3/Doc/zsh_us.ps
521           $ print **/zsh_us.ps
522           zsh-4.2.3/Doc/zsh_us.ps
523
524           # Search for `README' in all Subdirectories
525             $ ls -l **/README
526
527           # find directories that contain both "index.php" and "index.html", or in
528           # general, directories that contain more than one file matching "index.*"
529             $ ls **/*(D/e:'[[ -e $REPLY/index.php && -e $REPLY/index.html ]]':)
530             # or
531             $ ls **/*(D/e:'l=($REPLY/index.*(N)); (( $#l >= 2 ))':)
532
533           # Find command to search for directory name instead of basename
534             $ print -rl /**/*~^*/path(|/*)
535             # or - without Zsh
536             $ find / | grep -e /path/ -e '/path$'
537
538           # Print he path of the directories holding the ten biggest C regular files
539           # in the current directory and subdirectories.
540             $ print -rl -- **/*.c(D.OL[1,10]:h) | sort -u
541
542           # Find files with size == 0 and send a mail
543             $ files=(**/*(ND.L0m+0m-2))
544             > (( $#files > 0 )) && print -rl -- $files | \
545               mailx -s "empty files" foo@bar.tdl
546
547           # recursive chmod
548             $ chmod 700 **/(.) # Only files
549             $ chmod 700 **/(/) # Only directories
550
551           # print out all of the files in that directory in 2 columns
552             $ print -rC2 -- ${1:[...]}/*(D:t)
553           #            ^- number ob columns
554           # or - if you feel concerned about special characters - use
555             $ list=(${1:[...]}/*(ND:t))
556             $ (($#list)) && print -rC2 -- ${(V)list}
557
558           # Search all files in /home/*/*-mail/ with a setting ``chmod -s'' flag
559           # (recursive, include  dotfiles) remove the setgid/setuid flag and print
560           # a message
561             $ chmod -s /home/*/*-mail(DNs,S) /home/*/*-mail/**/*(DNs,S))
562           # or with a small script
563             $ for file (/home/*/*-mail(DNs,S) /home/*/*-mail/**/*(DNs,S)) {
564             >    print -r -- $file
565             >    chmod -s $file && print -r fixed $file
566             > }
567           # or use ``zargs'' (require autoload zargs) prevent the arg list too
568           # long error
569             $ zargs /home/*/*-mail(DNs,S) /home/*/*-mail/**/*(DNs,S)) -- chmod -s
570
571           # List files beginning at `foo23' upwards (foo23, foo24, foo25, ..)
572             $ ls -l foo<23->
573
574           # get all files that begin with the date strings from June 4 through
575           # June 9 of 2004
576             $ ls -l 200406{04..10}*(N)
577           # or if they are of the form 200406XX (require ``setopt extended_glob''
578             $ ls -l 200306<4-10>.*
579
580           # remove spaces from filenames
581             $ for a in ./**/*\ *(Dod); do mv $a ${a:h}/${a:t:gs/ /_}; done
582
583           # Show only all *.c and *.h - Files
584             $ ls -l *.(c|h)
585
586           # Show only all *.c - files and ignore `foo.c'
587             $ ls *.c~foo.c
588
589           # show data to *really* binary format
590             $ zsh -ec 'while {} {printf %.8x $n;repeat 8 \
591             > {read -ku0 a printf \ %.8d $(([##2]#a))};print;((n+=8))}' < binary
592
593           # Show only world-readable files
594             $ ls -l *(R)
595
596           # List files in the current directory are not writable by the owner
597             $ print -l ~/*(ND.^w)
598
599           # find and delete the files which are older than a given parameter
600           # (seconds/minutes/hours)
601             # deletes all regular file in /Dir that are older than 3 hours
602              $ rm -f /Dir/**/*(.mh+3)
603             # deletes all symlinks in /Dir that are older than 3 minutes
604              $ rm -f /Dir/**/*(@mm+3)
605             # deletes all non dirs in /Dir that are older than 30 seconds
606              $ rm -f /Dir/**/*(ms+30^/)
607             # deletes all folders, sub-folders and files older than one hour
608              $ rm ./**/*(.Dmh+1,.DL0)
609             # deletes all files more than 6 hours old
610              $ rm -f **/*(mh+6)
611             # removes all files but the ten newer ones (delete all but last 10
612             # files in a directory)
613              $ rm ./*(Om[1,-11])
614            Note: If you get a arg list too long, you use the builtin rm. For
615                  example:
616              $ zmodload zsh/files ; rm -f **/*(mh+6)
617             or use the zargs function:
618              $ autoload zargs ; zargs **/*(mh+6) -- rm -f
619
620           # A User's Guide to the Z-Shell /5.9: Filename Generation and Pattern
621           # Matching find all files in all subdirectories, searching recursively,
622           # which have a given name, case insensitive, are at least 50 KB large,
623           # no more than a week old and owned by the root user, and allowing up
624           # to a single error in the spelling of the name. In fact, the required
625           # expression looks like this:
626             $ ls **/(#ia1)name(LK+50mw-1u0)
627
628           # Change the UID from 102 to 666
629             $ chown 666 **/*(u102)
630
631           # List all files which have not been updated since last 10 hours
632             $ print -rl -- *(Dmh+10^/)
633
634           # delete only the oldest file in a directory
635             $ rm ./*filename*(Om[1])
636
637           # Sort the output from `ls -l' by file size
638             $ ls -fld *(OL)
639
640           # find most recent file in a directory
641             $ setopt dotglob ; print directory/**/*(om[1])
642
643           # Show only empty files which nor `group' or `world writable'
644             $ ls *(L0f.go-w.)
645
646           # Find - and list - the ten newest files in directories and subdirs.
647           # (recursive)
648             $ print -rl -- **/*(Dom[1,10])
649
650           # Print only 5 lines by "ls" command (like ``ls -laS | head -n 5'').
651             $ ls -fl *(DOL[1,5])
652
653           # Display the 5-10 last modified files.
654             $ print -rl -- /path/to/dir/**/*(D.om[5,10])
655
656           # Find all files without a valid owner.
657             $ chmod someuser /**/*(D^u:${(j.:u:.)${(f)"$(</etc/passwd)"}%%:*}:)
658
659           # Find all the empty directories in a tree.
660             $ for f in ***/*(/l2); do foo=($f/*(N)); [[ -z $foo ]] && print $f; done
661           # Note:Since Zsh 4.2.1 the glob qualifier F indicates a non-empty directory.
662           # Hence *(F) indicates all subdirectories with entries, *(/^F) means all
663           # subdirectories with no entries.
664             $ ls -ld *(/^F)
665
666           # Remove empty directories afterwards.
667             $ rmdir ./**/*(/od) 2> /dev/null
668
669           # Show only files which are owned by group `users'.
670             $ ls -l *(G[users])
671
672   Modifiers usage
673       Modifiers are a powerful mechanism that let you modify the results
674       returned by parameter, filename and history expansion. See zshexpn(1)
675       for details.
676
677           # NOTE: Zsh 4.3.4 needed!
678             $ autoload -U age
679           # files modified today
680             $ print *(e:age today now:)
681           # files modified since 5 pm
682             $ print *(e-age 17:00 now-)
683           # ... since 5 o'clock yesterda
684             $ print *(e-age yesterday,17:00 now-)
685           # ... from last Christmas before today
686             $ print *(e-age 2006/12/25 today-)
687           # ... before yesterday
688             $ print *(e-age 1970/01/01 yesterday-)
689           # all files modified between the start of those dates
690             $ print *(e:age 2006/10/04 2006/10/09:)
691           # all files modified on that date
692             $ print *(e:age 2006/10/04:)
693           # Supply times.
694             $ print *(e-age 2006/10/04:10:15 2006/10/04:10:45-)
695
696           # Remove a trailing pathname component, leaving the head. This works like
697           # `dirname'.
698             $ echo =ls(:h)
699             /bin
700
701           # Remove all leading pathname components, leaving the tail. This works
702           # like `basename'.
703             $ echo =ls(:t)
704             ls
705
706           # Remove the suffix from each file (*.sh in this example)
707              $f:e is $f file extension
708              :h --> head (dirname)
709              :t --> tail (basename)
710              :r --> rest (extension removed)
711             $ for f (*.sh) mv $f $f:r
712
713           # Remove a filename extension of the form `.xxx', leaving the root name.
714             $ echo $PWD
715             /usr/src/linux
716             $ echo $PWD:t
717             linux
718
719           # Remove all but the extension.
720             $ foo=23.42
721             $ echo $foo
722             23.42
723             $ echo $foo:e
724             42
725
726           # Print the new command but do not execute it. Only works with history
727           # expansion.
728             $ echo =ls(:h)
729             /bin
730             $ !echo:p
731             $ echo =ls(:h)
732
733           # Quote the substituted words, escaping further substitutions.
734             $ bar="23'42"
735             $ echo $bar
736             23'42
737             $ echo $bar:q
738             23\'42
739
740           # Convert the words to all lowercase.
741             $ bar=FOOBAR
742             $ echo $bar
743             FOOBAR
744             $ echo $bar:l
745             foobar
746
747           # Convert the words to all uppercase.
748             $ bar=foobar
749             $ echo $bar
750             foobar
751             $ echo $bar:u
752             FOOBAR
753
754           # convert 1st char of a word to uppercase
755             $ foo="one two three four"
756             $ print -r -- "${(C)foo}"
757             One Two Three Four
758
759   Redirection-Examples
760       See zshmisc(1) for more information (or less ${^fpath}/zmv(N))
761
762           # Append `exit 1' at the end of all *.sh - files
763             $ echo "exit 1" >> *.sh
764
765           # adding files to foobar.tar.gz
766             $ eval set =(gunzip < foobar.tar.gz) '
767                tar rf $1 additional.txt &&gzip < $1 > foobar.tar.gz'
768
769           # Redirect output to a file AND display on screen
770             $ foobar >&1 > file1 > file2 > ..
771
772           # pipe single output to multiple inputs
773             $ zcat foobar.Z >> (gzip -9 > file1.gz) \
774                 >> (bzip2 -9 > file1.bz2) \
775                 >> (acb --best > file1.acb)
776
777           # Append /etc/services at the end of file `foo' and `bar'
778             $ cat /etc/services >> foo >> bar
779
780           # Pipe STDERR
781             $ echo An error >&2 2>&1 | sed -e 's/A/I/'
782
783           # send standard output of one process to standard input of several processes
784           # in the pipeline
785             $ setopt multios
786             $ process1 > >(process1) > >(process2)
787
788           # initializing a variable and simultaneously keeping terminal output
789             $ setopt multios
790             $ { a=$(command >&1 >& 3 3 > &- 2>&1);} 3>&1
791
792           # redirect stderr two times
793             $ setopt multios ; program 2> file2 > file1 2>&1
794
795           # Duplicating stdout and stderr to a logfile
796             $ exec 3>&1 > logfile 2>&2 2>&1 >&3 3>&-
797
798           # redirect stderr (only) to a file and to orig. stderr:
799             $ command 2>&2 2>stderr
800           # redirect stderr and stdout to separate files and both to orig. stdout:
801             $ command 2>&1 1>&1 2>stderr 1>stdout
802           # redirect stderr and stdout to separate files and stdout to orig. stdout
803           # AND stderr to orig. stderr:
804             $ command 2>&2 1>&1 2>stderr 1>stdout
805
806           # More fun with STDERR ;)
807             $ ./my-script.sh 2> >(grep -v moron >error.log)|process-output >output.log
808             $  echo "Thats STDOUT" >>(sed 's/stdout/another example/' > foobar)
809
810   ZMV-Examples (require autoload zmv)
811       Note: -n means no execution (just print what would happen). At
812
813           # Remove illegal characters in a fat32 file system. Illegal characters are
814           #   / :  ;  *  ?  "  <  >  |
815           # NOTE: ``-Q'' and (D) is to include hidden files.
816             $ unwanted='[:;*?\"<>|]'
817             $ zmv -Q "(**/)(*$~unwanted*)(D)" '$1${2//$~unwanted/}'
818
819           # Changing part of a filename (i. e. "file-hell.name" -> "file-heaven.name")
820             $ zmv '(*)hell(*)' '${1}heaven${2}'
821             # or
822             $ zmv '*' '$f:s/hell/heaven/'
823
824           # remove round bracket within filenames
825           # i. e. foo-(bar).avi -> foo-bar.avi
826             $ zmv '*' '${f//[()]/}'
827
828           # serially all files (foo.foo > 1.foo, fnord.foo > 2.foo, ..)
829             $ autoload zmv
830             $ ls *
831             1.c  asd.foo  bla.foo  fnord.foo  foo.fnord  foo.foo
832             $ c=1 zmv '*.foo' '$((c++)).foo'
833             $ ls *
834             1.c  1.foo  2.foo  3.foo  4.foo  foo.fnord
835
836           # Rename "file.with.many.dots.txt" by substituting dots (except for the last
837           # one!) with a space
838             $ touch {1..20}-file.with.many.dots.txt
839             $ zmv '(*.*)(.*)' '${1//./ }$2'
840
841           # Remove the first 4 chars from a filename
842             $ zmv -n '*' '$f[5,-1]' # NOTE: The "5" is NOT a mistake in writing!
843
844           # Rename names of all files under the current Dir to lower case, but keep
845           # dirnames as-is.
846             $ zmv -Qv '(**/)(*)(.D)' '$1${(L)2}'
847
848           # replace all 4th character, which is "1",  with "2" and so on
849             $ autoload -U zmv
850             $ zmv '(???)1(???[1-4].txt)' '${1}2${2}'
851
852           # Remove the first 15 characters from a string
853             $ touch 111111111111111{a-z}
854             $ autoload zmv
855             $ zmv '*' '$f[16,-1]'
856
857           # Replace spaces (any number of them) with a single dash in file names
858             $ autload zmv
859             $ zmv -n '(**/)(* *)' '$1${2//( #-## #| ##)/-}'
860             # or - with Bash
861             $ find . -depth -name '* *' -exec bash -c '
862             > shopt -s extglob
863             > file=$1
864             > dir=${file%/*}
865             > name=${file##*/}
866             > newname=${name//*([ -]) *([ -])/-}
867             > mv -i -- "$file" "$Dir/$newname"' {} {} \;
868
869           # Clean up file names and remove special characters
870             $ autoload zmv
871             $ zmv -n '(**/)(*)' '$1${2//[^A-Za-z0-9._]/_}'
872
873           # Add *.py to a bunch of python scripts in a directory (some of them end
874           # in *.py and give them all a proper extension
875             $ autoload zmv
876             $ zmv -n '(**/)(con*)(#qe,file $REPLY | grep "python script",)' '$1$2.py'
877
878           # lowercase all extensions (i. e. *.JPG) incl. subfolders
879             $ autoload zmv
880             $ zmv '(**/)(*).(#i)jpg' '$1$2.jpg'
881             # Or - without Zsh
882             $ find Dir -name '*.[jJ][pP][gG]' -print | while read f
883             > do
884             >      case $f in
885             >       *.jpg) ;
886             >       *) mv "$f" "${f%.*}.jpg" ;
887             >       esac
888             > done
889
890           # remove leading zeros from file extension
891             $ autoload zmv
892             $ ls
893             filename.001  filename.003  filename.005  filename.007  filename.009
894             filename.002  filename.004  filename.006  filename.008  filename.010
895             $ zmv '(filename.)0##(?*)' '$1$2'
896             $ ls
897             filename.1  filename.10  filename.2  filename.3  filename.4  filename.5 ..
898
899           # renumber files.
900             $ autoload zmv
901             $ ls *
902             foo_10.jpg  foo_2.jpg  foo_3.jpg  foo_4.jpg  foo_5.jpg  foo_6.jpg ..
903             $ zmv -fQ 'foo_(<0->).jpg(.nOn)' 'foo_$(($1 + 1)).jpg'
904             $ ls *
905             foo_10.jpg  foo_11.jpg  foo_3.jpg  foo_4.jpg  foo_5.jpg  ...
906
907           # adding leading zeros to a filename (1.jpg -> 001.jpg, ..
908             $ autoload zmv
909             $ zmv '(<1->).jpg' '${(l:3::0:)1}.jpg'
910
911           # See above, but now only files with a filename >= 30 chars
912             $ autoload zmv
913             $ c=1 zmv "${(l:30-4::?:)}*.foo" '$((c++)).foo'
914
915           # Replace spaces in filenames with a underline
916             $ autoload zmv
917             $ zmv '* *' '$f:gs/ /_'
918
919           # Change the suffix from *.sh to *.pl
920             $ autoload zmv
921             $ zmv -W '*.sh' '*.pl'
922
923           # Add a "".txt" extension to all the files within ${HOME}
924             # ``-.'' is to only rename regular files or symlinks to regular files,
925             # ``D'' is to also rename hidden files (dotfiles))
926             $ autoload zmv
927             $ zmv -Q '/home/**/*(D-.)' '$f.txt'
928             # Or to only rename files that don't have an extension:
929             $ zmv -Q '/home/**/^?*.*(D-.)' '$f.txt'
930
931           # Recursively change filenames with characters ? [ ] / = + < > ; : " , - *
932             $ autoload zmv
933             $ chars='[][?=+<>;",*-]'
934             $ zmv '(**/)(*)' '$1${2//$~chars/%}'
935
936           # Removing single quote from filenames (recursively)
937             $ autoload zmv
938             $ zmv -Q "(**/)(*'*)(D)" "\$1\${2//'/}"
939
940           # When a new file arrives (named file.txt) rename all files in order to
941           # get (e. g. file119.txt becomes file120.txt, file118.txt becomes
942           # file119.txt and so on ending with file.txt becoming file1.txt
943             $ autoload zmv
944             $ zmv -fQ 'file([0-9]##).txt(On)' 'file$(($1 + 1)).txt'
945
946           # lowercase/uppercase all files/directories
947             $ autoload zmv
948             $ zmv '(*)' '${(L)1}' # lowercase
949             $ zmv '(*)' '${(U)1}' # uppercase
950
951           # Remove the suffix *.c from all C-Files
952             $ autoload zmv
953             $ zmv '(*).c' '$1'
954
955           # Uppercase only the first letter of all *.mp3 - files
956             $ autoload zmv
957             $ zmv '([a-z])(*).mp3' '${(C)1}$2.mp3'
958
959           # Copy the target `README' in same directory as each `Makefile'
960             $ autoload zmv
961             $ zmv -C '(**/)Makefile' '${1}README'
962
963           # Removing single quote from filenames (recursively)
964             $ autoload zmv
965             $ zmv -Q "(**/)(*'*)(D)" "\$1\${2//'/}"
966
967           # Rename pic1.jpg, pic2.jpg, .. to pic0001.jpg, pic0002.jpg, ..
968             $ autoload zmv
969             $ zmv 'pic(*).jpg' 'pic${(l:4::0:)1}.jpg'
970             $ zmv '(**/)pic(*).jpg' '$1/pic${(l:4::0:)2}.jpg' # recursively
971
972   Module-Examples
973       Please read zshmodules(1) first!
974
975       zsh/pcre (require zmodload zsh/pcre)
976               # Copy files of a certain period (date indicated in the filenames)
977                 $ zmodload zsh/pcre
978                 $ ls -d -- *(e:'[[ $REPLY -pcre-match pcre-regexp ]]':)
979                 # or
980                 $ m() { [[ $1 -pcre-match pcre-regexp ]] }
981                 $ ls -d -- *(+m)
982
983       zsh/clone (require zmodload zsh/clone)
984               # Creates a forked instance of the current shell ($! is set to zero) and
985               # execute ``command'' on /dev/tty8 (for this example).
986                 $ zmodload zsh/clone
987                 $ clone /dev/tty8 && (($! == 0)) && exec command
988
989       zsh/datetime (require zmodload zsh/datetime)
990                 $ zmodload zsh/datetime
991                 $ alias datereplacement='strftime "%Y-%m-%d" $EPOCHSECONDS'
992                 $ export DATE=`datereplacement`
993                 $ echo $DATE
994
995               #  strip date from filename
996                 $ $ zmodload zsh/datetime
997                 $ setopt extendedglob
998                 $ touch aaa_bbb_20041212_c.dat eee_fff_20051019_g.dat
999                 $ strftime -s pattern \
1000                   '???_???_<0-%Y%m%d>_?.dat' $((EPOCHSECONDS - 365 * 24 * 60 * 60 / 2))
1001                 $ print -rl -- $~pattern
1002                 aaa_bbb_20041212_c.dat
1003                 $ print -rl -- $pattern
1004                 ???_???_<0-20050815>_?.dat
1005
1006               # Search files size == 0, to be based on the file name containing a date
1007               # rather than the "last modified" date of the file
1008                 $ zmodload -i zsh/datetime
1009                 $ strftime -s file "abc_de_%m%d%Y.dat" $((EPOCHSECONDS - 24 * 60 * 60 ))
1010                 $ files=(**/$file(N.L0))
1011                 $ (( $#files > 0 )) && print -rl -- $files | \
1012                   mailx -s "empty files"  foo@bar.tdl
1013
1014       zsh/stat (require zmodload zsh/stat)
1015               # test if a symbolic link links to a certain file
1016                 $ zmodload -i zsh/stat
1017                 $ ! stat -LH s foo.ln || [[ $s[link] != "foo.exe" ]] || ln -sf foo.exe foo.ln
1018
1019               # comparing file dates
1020                 $ zmodload zsh/stat
1021                 $ file1=foo
1022                 $ file2=bar
1023                 $ touch bar & sleep 5 & touch foo
1024                 $ echo $file1 is $(($(stat +mtime $file2) - \
1025                   $(stat +mtime $file1))) seconds older than $file2.
1026                 bar is 5 seconds older than foo
1027
1028               # list the files of a disk smaller than some other file
1029                 $ zmodload zsh/stat
1030                 $ stat -A max +size some-other-file
1031                 $ print -rl ./**/*(D.L-$max)
1032
1033               # List the top 100 biggest files in a disk
1034                 $ zmodload zsh/stat
1035                 $ ls -fld ./**/*(d`stat +device .`OL[1,100])
1036
1037               # Get only the user name and the file names from (like
1038               # ls -l * | awk '{print $3" " $8}')
1039                 $ zmodload zsh/stat
1040                 $ for file; do
1041                 >   stat -sA user +uid -- "$file" &&
1042                 >     print -r -- "$user" "$file"
1043                 > done
1044
1045               # get the difference between actual bytes of file and allocated bytes of file
1046                 $ zmodload zsh/stat
1047                 $ print $(($(stat +block -- file) * 512 - $(stat +size -- file)))
1048
1049               # Find largest file
1050               # ``D''  : to include dot files (d lowercase is for device)
1051               # ``O''  : reverse Ordered (o lowercase for non-reverse order)
1052               # ``L''  : by file Length (l is for number of links)
1053               # ``[1]'': return only first one
1054                 $ zmodload zsh/stat
1055                 $ stat +size ./*(DOL[1])
1056
1057               # file size in bytes
1058                 $ zmodload zsh/stat
1059                 $ stat -L +size ~/.zshrc
1060                 4707
1061
1062               # Delete files in a directory that hasn't been accessed in the last ten days
1063               # and send ONE mail to the owner of the files informing him/her of the files'
1064               # deletion.
1065                 $ zmodload zsh/stat zsh/files
1066                 $ typeset -A f; f=()
1067                 $ rm -f /path/**/*(.a+10e{'stat -sA u +uidr $REPLY; f[$u]="$f[$u]$REPLY"'})
1068                 $ for user (${(k)f}) {print -rn $f[$user]|mailx -s "..." $user}
1069
1070               # Get a "ls -l" on all the files in the tree that are younger than a
1071               # specified age
1072                 $ zmodload zsh/stat
1073                 $ for d (. ./**/*(N/m-2))
1074                 >   print -r -- $'\n'$d: && cd $d && {
1075                 >      for f (*(Nm-2om))
1076                 >   stat -F '%b %d %H:%M' -LsAs -- $f &&
1077                 >   print -r -- $s[3] ${(l:4:)s[4]} ${(l:8:)s[5]} \
1078                 >   ${(l:8:)s[6]} ${(l:8:)s[8]} $s[10] $f ${s[14]:+-> $s[14]}
1079                 >   cd ~-
1080                 > }
1081
1082               # get file creation date
1083                 $ zmodload zsh/stat
1084                 $ stat -F '%d %m %Y' +mtime ~/.zshrc
1085                 30 06 2004
1086                 $ stat -F '%D' +mtime ~/.zshrc
1087                 06/30/04
1088
1089       zsh/files (require zmodload zsh/files)
1090               # search a directory for files containing a certain string then copy those
1091               # files to another directory.
1092                 $ zmodload zsh/files
1093                 $ IFS=$'\0'
1094                 $ cp $(grep -lZr foobar .) otherdirectory
1095
1096       zsh/mapfile (require zmodload zsh/mapfile)
1097               # grepping for two patterns
1098                 $ zmodload zsh/mapfile
1099                 $ pattern1="foo"
1100                 $ pattern2="bar foo"
1101                 $ print -l ./**/*(DN.e{'z=$mapfile[$REPLY] && [[ $z = *$pattern1* && \
1102                   $z = *$pattern2* ]]'})
1103               # or a solution in combination with zsh/pcre
1104                 $ zmodload -i zsh/mapfile zsh/pcre
1105                 $ pattern1="foo"
1106                 $ pattern2="bar foo"
1107                 $ pcre_compile "(?s)(?=.*?$pattern1).*?$pattern2"
1108                 $ pcre_study
1109                 $ print -l ./**/*(DN.e{'pcre_match $mapfile[$REPLY]'})
1110
1111               # equivalent for ``less /etc/passwd | grep -v root''
1112                 $ zmodload zsh/mapfile
1113                 $ IFS=$'\n\n'
1114                 $ print -rl -- ${${=mapfile[/etc/passwd]}:#*root*}
1115               # or - for case insensitive
1116                 $ setopt extendedglob
1117                 $ print -rl -- ${${=mapfile[/etc/passwd]}:#*(#i)root*}
1118
1119               # If a XML-file contains stuff like ``<TAGA/>'' and ``<TAGB/>'', number
1120               # this empty tags (ones ending in '/>') so if encountered in the same
1121               # order, the preceding tags would become ``<TAGA/>1</TAGA>'' and
1122               # ``<TAGB/>2</TAGB>''
1123                 $ zmodload zsh/mapfile
1124                 $ cnt=0
1125                 $ apfile[data.xml.new]=${(S)mapfile[data.xml]//\
1126                 > (#im)<TAGA>*<\/TAGA>/<TAGA>$((++cnt))<\/TAGA>}
1127
1128               # removing all files in users Maildir/new that contain ``filename="gone.src''
1129                 $ zmodload zsh/{files,mapfile}
1130                 $ rm -f /u1/??/*/Maildir/new/100*(.e{'[[ $mapfile[$REPLY] == \
1131                   *filename=\"gone.scr\"* ]]'})
1132
1133               # Grep out the Title from a postscript file and append that value to the
1134               # end of the filename
1135                 $ autoload -U zmv
1136                 $ zmodload zsh/mapfile
1137                 $ zmv '(*).ps' '$1-${${${mapfile[$f]##*%%Title: }%% *}//[^a-zA-Z0-9_]/}.ps'
1138
1139       zsh/mathfunc (require zmodload zsh/mathfunc)
1140               $ zmodload zsh/mathfunc
1141               $ echo $(( sin(1/4.0)**2 + cos(1/4.0)**2 - 1 ))
1142                 -1.1102230246251565e-16
1143               $ echo $(( pi = 4.0 * atan(1.0) ))
1144                 3.1415926535897931
1145               $ echo $(( f = sin(0.3) ))
1146                 0.29552020666133955
1147               $ print $((1e12 * rand48()))
1148                 847909677310.23413
1149               $ print $(( rand48(seed) ))
1150                 0.01043488334700271
1151
1152       zsh/termcap (require zmodload zsh/termcap)
1153                $ zmodload -ab zsh/termcap echotc
1154                $ GREEN=`echotc AF 2`
1155                $ YELLOW=`echotc AF 3`
1156                $ RED=`echotc AF 1`
1157                $ BRIGHTRED=`echotc md ; echotc AF 1`
1158                $ print -l ${GREEN}green ${YELLOW}yellow ${RED}red ${BRIGHTRED}brightred
1159
1160       zsh/zpty (require zmodload zsh/zpty)
1161                 $ zmodload zsh/zpty
1162                 $ zpty PW passwd $1
1163                 $ zpty PW passwd $1
1164               # ``-r'': read the output of the command name.
1165               # ``z'' : Parameter
1166                 $ zpty -r PW z '*password:'
1167               # send the to command name the given strings as input
1168                 $ zpty -w PW $2
1169                 $ zpty -r PW z '*password:'
1170                 $ zpty -w PW $2
1171               # The second form, with the -d option, is used to delete commands
1172               # previously started, by supplying a list of their names. If no names
1173               # are given, all commands are deleted. Deleting a command causes the HUP
1174               # signal to be sent to the corresponding process.
1175                 $ zpty -d PW
1176
1177       zsh/net/socket (require zmodload zsh/net/socket)
1178               # ``-l'': open a socket listening on filename
1179               # ``-d'': argument will be taken as the target file descriptor for the
1180               #         connection
1181               # ``3'' : file descriptor. See ``A User's Guide to the Z-Shell''
1182               #         (3.7.2: File descriptors)
1183                 $ zmodload zsh/net/socket
1184                 $ zsocket -l -d 3
1185               # ``-a'': accept an incoming connection to the socket
1186                 $ zsocket -a -d 4 3
1187                 $ zsocket -a -d 5 3 # accept a connection
1188                 $ echo foobar >&4
1189                 $ echo barfoo >&5
1190                 $ 4>&- 5>&- 3>&
1191
1192       zsh/zftp (require zmodload zsh/zftp)
1193                $ autoload -U zfinit
1194                $ zfinit
1195                $ zfparams www.example.invalid myuserid mypassword
1196                $ zfopen
1197                $ zfcd tips
1198                $ zfls -l zshtips.html
1199                $ zfput zshtips.html
1200                $ zfls -l zshtips.html
1201
1202               # Automatically transfer files using FTP with error checking
1203                 $ autoload -U zfinit ; zfinit
1204                 $ zftp open host.name.invalid user passwd || exit
1205                 $ zftp get /remote/file > /local/file; r=$?
1206                 $ zftp close && exit r
1207
1208               # compress and ftp on the fly
1209                 $ autoload -U zfinit ; zfinit
1210                 $ zftp open host.name.invalid user password
1211                 $ zftp get $file | bzip2 > ${file}.bz2
1212                 $ zftp close
1213
1214               # Recursice ``get''
1215                 $ autoload -U zfinit ; zfinit
1216                 $ zfanon cr.yp.to
1217                 $ zfcd daemontools
1218                 $ for file in `zfls` ; do
1219                 >     zfget $file
1220                 $ done
1221                 $ zfclose
1222
1223               # Upload all regular files in $HOME/foobar (recursive) that are newer than
1224               # two hours to ftp.foobar.invalid/path/to/upload
1225                 $ autoload -U zfinit ; zfinit
1226                 $ zfopen ftp.foobar.invalid/path/to/upload
1227                 $ cd $HOME/foobar
1228                 $ zfput -r **/*(.mh-2)
1229                 $ zfclose
1230
1231               # long list of files on a ftp
1232                 $ autoload -U zfinit ; zfinit
1233                 $ zfopen some-host
1234                 $ zfcd /some/remote/Dir
1235                 $ cd /some/local/Dir
1236               # If the list.txt is located on the remote host, change to
1237               # zfget ${(f)"$(zftp get /path/to/remote/list.txt)"}
1238                 $ zfget ${(f)"$(cat list.txt)"}
1239                 $ zfclose
1240
1241       zsh/zselect (require zmodload zsh/zselect)
1242               # It's similar to
1243                ,----
1244                | $ sg=$(stty -g)
1245                | $ stty -icanon min 0 time 50
1246                | $ read yesno
1247                | $ stty "$sg"
1248                | $ case "$yesno" in
1249                | >  yes) command1;;
1250                | >  *) command2;;
1251                | > esac
1252                `----
1253               $ zmodload zsh/zselect
1254               $ if zselect -t 500 -r 0 && read yesno && [ yes = "$yesno" ]; then
1255               >    command1
1256               > else
1257               >    command1
1258               > fi
1259

OPTIONS

1261   Navigation options
1262       auto_cd (allow one to change to a directory by entering it as a
1263       command). auto_pushd (automatically append dirs to the push/pop list)
1264       pushd_ignore_dups (and don’t duplicate them).
1265
1266   Misc
1267       no_hup (don’t send HUP signal to background jobs when exiting ZSH).
1268       print_exit_value (show a message with the exit code when a command
1269       returns with a non-zero exit code)
1270
1271       History options
1272           hist_verify (let the user edit the command line after history
1273           expansion (e.g. !ls) instead of immediately running it) Use the
1274           same history file for all sessions : setopt SHARE_HISTORY
1275
1276       Privacy / Security
1277           no_clobber (or set -C; prevent > redirection from truncating the
1278           given file if it already exists)
1279
1280       Spelling correction
1281           correct (automatically correct the spelling of commands).
1282           correct_all (automatically correct the spelling of each word on the
1283           command line) dvorak (dvorak layout)
1284

UNSORTED/MISC

1286       Mailpath: simple multiple mailpath:
1287
1288           mailpath=($HOME/Mail/mbox'?new mail in mbox'
1289                     $HOME/Mail/tux.u-strasbg'?new mail in tux'
1290                     $HOME/Mail/lilo'?new mail in lilo'
1291                     $HOME/Mail/ldap-fr'?new mail in ldap-fr')
1292
1293       Mailpath: dynamic mailpath:
1294
1295           typeset -a mailpath
1296           for i in ~/Mail/Lists/*(.); do
1297              mailpath[$#mailpath+1]="${i}?You have new mail in ${i:t}."
1298           done
1299
1300       Avoid globbing on special commands:
1301
1302           for com in alias expr find mattrib mcopy mdir mdel which;
1303           alias $com="noglob $com"
1304
1305       For migrating your bashprompt to zsh use the script bash2zshprompt
1306       located in the zsh source distribution under Misc.
1307
1308       For migration from (t)csh to zsh use the c2z tool that converts csh
1309       aliases and environment and shell variables to zsh. It does this by
1310       running csh, and having csh report on aliases and variables. The script
1311       then converts these to zsh startup files. It has some issues and usage
1312       information that are documented at the top of this script.
1313
1314       Here are functions to set the title and hardstatus of an XTerm or of
1315       GNU Screen to zsh and the current directory, respectively, when the
1316       prompt is displayed, and to the command name and rest of the command
1317       line, respectively, when a command is executed:
1318
1319           function title {
1320                 if [[ $TERM == "screen" ]]; then
1321                   # Use these two for GNU Screen:
1322                   print -nR $' 33k'$1$' 33'\
1323                   print -nR $' 33]0;'$2$''
1324                 elif [[ $TERM == "xterm" || $TERM == "rxvt" ]]; then
1325                   # Use this one instead for XTerms:
1326                   print -nR $' 33]0;'$*$''
1327                 fi
1328           }
1329           function precmd { title zsh "$PWD" }
1330           function preexec {
1331               emulate -L zsh
1332               local -a cmd; cmd=(${(z)1})
1333               title $cmd[1]:t "$cmd[2,-1]"
1334           }
1335
1336       Put the following line into your ~/.screenrc to see this fancy
1337       hardstatus:
1338
1339           caption always "%3n %t%? (%u)%?%?: %h%?"
1340
1341       Special variables which are assigned:
1342
1343           $LINENO $RANDOM $SECONDS $COLUMNS $HISTCHARS $UID
1344           $EUID $GID $EGID $USERNAME $fignore $mailpath $cdpath
1345
1347       Primary site
1348           http://www.zsh.org/
1349
1350       Zsh Web Pages
1351           https://zsh.sourceforge.io/
1352
1353       Project-page
1354           http://sourceforge.net/projects/zsh/
1355
1356       From Bash to Z Shell: Conquering the Command Line - the book
1357           http://www.bash2zsh.com/
1358
1359       "Zsh - die magische Shell" (german book about Zsh) by Sven Guckes and
1360       Julius Plenz
1361           http://zshbuch.org/
1362
1363       Mailinglistarchive
1364           http://www.zsh.org/mla/
1365
1366       ZSH-FAQ
1367           https://zsh.sourceforge.io/FAQ/zshfaq.html
1368
1369       Userguide
1370           https://zsh.sourceforge.io/Guide/
1371
1372       ZSH-Wiki
1373           http://zshwiki.org/home/
1374
1375       Mouse-Support ;)
1376           http://stchaz.free.fr/mouse.zsh
1377
1378       ZSH Prompt introduction
1379           http://aperiodic.net/phil/prompt/
1380
1381       ft’s zsh configuration
1382           http://ft.bewatermyfriend.org/computer/zsh.html
1383
1384       Adam’s ZSH page
1385           http://www.adamspiers.org/computing/zsh/
1386
1387       Zzappers Best of ZSH Tips
1388           http://www.rayninfo.co.uk/tips/zshtips.html
1389
1390       Zsh Webpage by Christian Schneider
1391           http://www.strcat.de/zsh/
1392
1393       The zsh-lovers webpage
1394           http://grml.org/zsh/
1395
1396       IRC channel
1397           #zsh at irc.freenode.org
1398
1399       The Z shell reference-card (included in the zsh-lovers debian-package)
1400           http://www.bash2zsh.com/zsh_refcard/refcard.pdf
1401

AUTHORS

1403       This manpage was written by Michael Prokop, Christian strcat Schneider
1404       and Matthias Kopfermann. But many ideas have been taken from zsh-geeks
1405       e.g. from the zsh-mailinglists (zsh-users and zsh-workers), google,
1406       newsgroups and the zsh-Wiki. Thanks for your cool and incredible tips.
1407       We learned much from you!
1408
1409       In alphabetic order:
1410
1411           Andrew 'zefram' Main  - http://www.fysh.org/~zefram/
1412           Barton E. Schaefer    - http://www.well.com/user/barts/
1413           Matthias Kopfermann   - http://www.guckes.net/zsh/lover.html
1414           Oliver Kiddle         - http://people.freenet.de/opk/
1415           Paul Falstad          - http://www.falstad.com/
1416           Peter Stephenson      - http://homepage.ntlworld.com/p.w.stephenson/
1417           Richard Coleman
1418           Stephane Chazelas     - http://stephane.chazelas.free.fr/
1419           Sven Guckes           - http://www.guckes.net/
1420           Sven Wischnowsky      - http://w9y.de/
1421

SEE ALSO

1423       Manpages of zsh:
1424
1425                  zsh          Zsh overview
1426                  zshall       Tthe Z shell meta-man page
1427                  zshbuiltins  Zsh built-in commands
1428                  zshcalsys    zsh calendar system
1429                  zshcompctl   zsh programmable completion
1430                  zshcompsys   Zsh completion system
1431                  zshcompwid   Zsh completion widgets
1432                  zshcontrib   User contributions to zsh
1433                  zshexpn      Zsh expansion and substitution
1434                  zshmisc      Anything not fitting into the other sections
1435                  zshmodules   Zsh loadable modules
1436                  zshoptions   Zsh options
1437                  zshparam     Zsh parameters
1438                  zshroadmap   Informal introduction to the zsh manual
1439                  zshtcpsys    Zsh tcp system
1440                  zshzle       Zsh command line editing
1441                  zshzftpsys   Zsh built-in FTP client
1442                  zshall       Meta-man page containing all of the above
1443
1444       Note: especially man zshcontrib covers very useful topics! Book: From
1445       Bash to Z Shell by Oliver Kiddle, Jerry Peck and Peter Stephenson.
1446       ISBN: 1590593766. - bash2zsh.com Also take a look at the section LINKS
1447       in this manpage.
1448

BUGS

1450       Probably. This manpage might be never complete. So please report bugs,
1451       feedback and suggestions via https://github.com/grml/zsh-lovers Thank
1452       you!
1453
1455       Copyright (C) Michael Prokop, Christian Schneider and Matthias
1456       Kopfermann.
1457
1458
1459
1460                                  09/10/2023                     ZSH-LOVERS(1)
Impressum