Send to Kindle
home » snippets » zsh


Sites Page



Simple Commands and Pipelines

See: Simple Commands & Pipelines

If a sublist is terminated by a ‘&’, ‘&|’, or ‘&!’, the shell executes the last pipeline in it in the background, and does not wait for it to finish (note the difference from other shells which execute the whole sublist in the background).


If the user has already set $MYPARAM, nothing happens, otherwise it will be set to default, and similarly for ${OTHERPARAM}. The : command does nothing but return true after the command line has been processed.

which here have the same effect of ${HOME:t} and and ${HOME:h}, and in zsh you would be more likely to use the latter. However, as you can see the pattern forms are much more general. Note the difference from:

% print ${HOME#*/}  
% print ${HOME%%/*}

so you need parentheses around them. This is a special case of `glob qualifiers' which you'll meet below; you can mix them, but the modifiers must appear at the end. For example,

% print -l ~/stuff/*  
% print ~/stuff/*(.:r:t)  
onefile twofile

The globbing qualifier . specifies that files must be regular, i.e. not directories nor some form of special file. The :r removes the suffix from the result, and the :t takes away the directory part.

foo.c(:r) will only strip off the suffix if foo.c is there in the current directory. This is perfectly logical given that the attempt to match a file kicks the globbing system, including modifiers, into action. If this is a problem for you, there are ways round; for example, insert the right value by hand in a simple case like this, or more realistically store the value in a parameter and apply the modifier to that.

Any character can follow the (s) or (j); the string argument lasts until the matching character, here .. If the character is one of the bracket-like characters including <, the matching' character is the corresponding right bracket, e.g.${(s<:>)PATH}and${(s(:))PATH}are both valid. This applies to all flags that need arguments, including(I)`.

Although the split or join string isn't a pattern, it doesn't have to be a single character:

  % foo=(array of words)  
  % print ${(j.**.)foo}  

The (z) flag doesn't take an argument. As it handles splitting on the full shell definition of a word, it goes naturally with quoted expressions, and I discussed above its use with the (Q) flag for extracting words from a line with the quotes removed.

It's possible for the same parameter expression to have both splitting and joining applied to it. This always occurs in the same order, regardless of how you specify the flags: joining first, then splitting. This is described in the (rather hairy) complete set of rules in the manual entry for parameter substitution. There are one or two occasions where this can be a bit surprising. One is when you have SH_WORD_SPLIT set and try to join a string:

  % setopt shwordsplit      
  % foo=('another array' of 'words with spaces')  
  % print -l ${(j.:.)foo}  

You might not have noticed if you didn't use the `-l option to print, but the spaces still caused word-spliting even though you asked for the array to be joined with colons. To avoid this, either don't use SH_WORD_SPLIT (my personal preference), or use quotes:

  % print -l "${(j.:.)foo}"  
  another array:of:words with spaces

The elements of an array would normally be joined by spaces in this case, but the character specified by the (j) flag takes precedence. In just the same way, if SH_WORD_SPLIT is in effect, any splitting string given by (s) is used instead of the normal set of characters, which are any characters that occur in the string $IFS, by default space, tab, newline and NUL.

Specifying a split for a particular parameter substitution not only sets the string to split on, but also ensures the split will take place even if the expression is quoted:

  % array=('element one' 'element two' 'element three')  
  % print -l "${=array}"  

To be clear about what's happening here: the quotes force the elements to be joined with spaces, giving a single string, which is then split on the original spaces as well as the one used to join the elements of the array.

I will talk shortly about nested parameter substitution; you should also note that splitting and joining will if necessary take place at all levels of a nested substitution, not just the outermost one:

  % foo="three blind words"  
  % print ${#${(z)foo}}  

This prints the length of the innermost expression; because of the zplit, that has produced a three-element array.