Links
- See also: globbing
man zshexpn
- Arithmetic Evaluation
- Expansion
- Parameter Expansion
- zshwiki: Parameter Expansion Flags
- docs: Parameter Expansion Flags
- Modifiers
Like
(:t)
for basename, etc. - Brace Expansion
- Examples
- zsh-lovers.html: UNSORTED/MISC examples
- Examples
*(-OL[1,3])
gives a list of the names of the three largest files.
Parameter Expansion
Some common ones
From: Parameter Expansion
Syntax | Description |
---|---|
{$name=word} |
if name is unset then set it to word |
${name:=word} |
if name is unset or null then set it to word |
${name::=word} |
unconditionally set name to word |
{$name-word} |
if name is set, then substitute its value; otherwise substitute word |
{$name:-word} |
if name is non-null, then substitute its value; otherwise substitute word |
{$name+word} |
if name is set, then substitute word; otherwise substitute nothing |
{$name:+word} |
if name is non-null, then substitute word; otherwise substitute nothing |
{$name?word} |
if name is set, then substitute its value; otherwise, print word and exit from the shell |
{$name:?word} |
if name is set and non-null, then substitute its value; otherwise, print word and exit from the shell |
Initializing a variable to a default value when not set
: ${FOO:=/tmp/$BAR}
Replacing cat
The substitution ‘$(cat foo)’
may be replaced by the
equivalent but faster ‘$(<foo)’
Find a specific parent directory
# Find the parent directory called "build" echo ${PWD/build*\//build}
Expand indirectly / recursively – (P)
`${(P)E}`
- double expand E
- i.e. if
E=EDITOR
andEDITOR=emacs,
then${(P)E}
=emacs
Rescan and expand – (e)
A more powerful flag is (e)
, which forces the value to be rescanned for all forms of single-word substitution. For example,
% foo='$(print $ZSH_VERSION)' % print ${(e)foo} 4.0.2
Word Splitting
# This forces word splitting while expanding E ${=E}
Split and Join
Use ps:X:
and pj:X:
. The (f/F)
flags are short for
ps:\n:
and pj:\n:
.
# Read lines from a file into an array. # Without the double quotes, you'll get just one long # line with all the newlines replaced by spaces (which # also prevents the splitting on newlines.) lines=(${(f)"$(<file)"}) # The double quotes are needed. # (F) does the opposite and joins items with a \n lines=(one two three) print ${(F)lines} # prints one\ntwo\nthree
Quoting
Quote E when it is expanded using \'s. If you use (qq)
instead, then use single quotes to quote it. And (qqq)
specifies using double quotes. (qqqq)
specifies using posix
quotes.
${(q)E}
It's very common, however, that you want one line per
argument, not splitting on spaces within the line. This is
where parameter expansion can come in. There is a flag (f)
which says split the result of the expansion, one word per line
.
Here's how to use it in this case:
$ args $(ls -l) 4592 $ args "${(f)$(ls -l)}" 490 $ text="$(ls -l)" $ args "${(f)text}" 490
Splitting and Joining
Ref: Parameter Expansion
Flags
(Search for Force field splitting at the separator string
)
Syntax:
s:string:
Force field splitting at the separator string. Note that
a string of two or more characters means that all of them
must match in sequence; this differs from the treatment of
two or more characters in the IFS
parameter. See also
the = flag and the SH_WORD_SPLIT
option. An empty string
may also be given in which case every character will be a
separate element.
NOTE: For historical reasons, the usual behaviour that empty array
elements are retained inside double quotes is disabled for
arrays generated by splitting. Override by using @s
instead of s
. The following:
line="one::three" print -l "${(s.:.)line}"
produces two lines of output for one and three and elides
the empty field. To override this behaviour, supply the
(@)
flag as well, i.e. ${(@s.:.)line}
.
Example:
# split on commas # prints A, B and C on 3 separate lines. print_args ${(s:,:)${:-A,B,,C}} # If we want the blank item, we must BOTH, add the @ flag as well as # stick the whole thing in double quotes. # prints A, B, empty string and C on 4 separate lines. print_args "${(@s:,:)${:-A,B,,C}}" # split on newlines # prints A, B and C on 3 separate lines. # NOTE: You need to use (ps:X:) and not (s:X:) if X contains # escapes that you want interpreted (e.g. \n) print_args ${(ps:\n:)${:-$'A\nB\nC'}}
Examples
Ref: http://grml.org/zsh/zsh-lovers.html#_unsorted_misc_examples
*(-OL[1,3])
gives a list of the names of the three largest files.- Find largest file
zmodload zsh/stat; stat +size ./*(DOL[1])
D
: to include dot files (d
lowercase is for device)O
: reverse Ordered (o
lowercase for non-reverse order)L
: by file Length (l
is for number of links)
ls *(-/)
- lists all directories and symbolic links that point to directories, and
ls *(%W)
- lists all world-writable device files in the current directory, and
ls *(W,X)
- lists all files in the current directory that are world-writable or world-executable, and
echo /tmp/foo*(u0^@:t)
- outputs the basename of all root-owned files beginning with the string ‘foo’ in /tmp, ignoring symlinks, and
ls *.*~(lex|parse).[ch](^D^l1)
- lists all files having a link count of one whose names contain a dot (but not those starting with a dot, since GLOB_DOTS is explicitly switched off) except for lex.c, lex.h, parse.c and parse.h.
print b*.pro(#q:s/pro/shmo/)(#q.:s/builtin/shmiltin/)
- demonstrates how colon modifiers and other qualifiers may be chained together. The ordinary qualifier ‘.’ is applied first, then the colon modifiers in order from left to right. So if EXTENDED_GLOB is set and the base pattern matches the regular file builtin.pro, the shell will print ‘shmiltin.shmo’.