diff options
Diffstat (limited to 'Doc/Zsh/expn.yo')
-rw-r--r-- | Doc/Zsh/expn.yo | 900 |
1 files changed, 582 insertions, 318 deletions
diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index ee554e6c1..eac35f6a9 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -1,36 +1,44 @@ -texinode(Expansion)(Parameters)(Restricted Shell)(Top) +texinode(Expansion)(Parameters)(Prompt Expansion)(Top) chapter(Expansion) cindex(expansion) -sect(Description) -The types of expansions performed are - -startlist() -list(em(History Expansion)) -list(em(Alias Expansion)) -list(em(Process Substitution)) -list(em(Parameter Expansion)) -list(em(Command Substitution)) -list(em(Arithmetic Expansion)) -list(em(Brace Expansion)) -list(em(Filename Expansion)) -list(em(Filename Generation)) -endlist() - -Expansion is done in the above specified order in five steps. The -first is em(history expansion), which is only performed in -interactive shells. The next step is em(alias expansion), which is -done right before the command line is parsed. They are followed by -em(process substitution), em(parameter expansion), em(command -substitution), em(arithmetic expansion) and em(brace expansion) -which are performed in one step in left-to-right fashion. After -these expansions, all unquoted occurrences of the characters `tt(\)', -`tt(')' and `tt(")' are removed, and the result is subjected to -em(filename expansion) followed by em(filename generation). +ifnztexi(sect(Description)) +The following types of expansions are performed in the indicated order in +five steps: -If the tt(SH_FILE_EXPANSION) option is set, the order of expansion is modified -for compatibility with bf(sh) and bf(ksh). em(Filename expansion) -is performed immediately after em(alias expansion), +startitem() +item(em(History Expansion))( +This is performed only in interactive shells. +) +item(em(Alias Expansion))( +Aliases are expanded immediately before the command line is parsed as +explained +ifzman(under Aliasing in zmanref(zshmisc))\ +ifnzman(in noderef(Aliasing))\ +. +) +xitem(em(Process Substitution)) +xitem(em(Parameter Expansion)) +xitem(em(Command Substitution)) +xitem(em(Arithmetic Expansion)) +item(em(Brace Expansion))( +These five are performed in one step in left-to-right fashion. After +these expansions, all unquoted occurrences of the characters `tt(\)', +`tt(')' and `tt(")' are removed. +) +item(em(Filename Expansion))( +If the tt(SH_FILE_EXPANSION) option is set, the order of expansion is +modified for compatibility with bf(sh) and bf(ksh). In that case +em(filename expansion) is performed immediately after em(alias expansion), preceding the set of five expansions mentioned above. +) +cindex(globbing) +item(em(Filename Generation))( +This expansion, commonly referred to as bf(globbing), is always done last. +) +enditem() + +The following sections explain the types of expansion in detail. + startmenu() menu(History Expansion) menu(Process Substitution) @@ -49,36 +57,93 @@ cindex(expansion, history) History expansion allows you to use words from previous command lines in the command line you are typing. This simplifies spelling corrections and the repetition of complicated commands or arguments. -Command lines are saved in the history list, the size of which -is controlled by the tt(HISTSIZE) vindex(HISTSIZE, use of) -parameter. The most recent command is retained in any case. -A history expansion begins with the first character of the -tt(histchars) parameter which is `tt(!)' -by default and may occur anywhere on the command line; history -expansions do not nest. The `tt(!)' can be escaped with `tt(\)' -or can be enclosed between a pair of single quotes (tt('')) to suppress -its special meaning. Double quotes will em(not) work for this. - -Input lines containing history expansions are echoed on the -terminal after being expanded, but before any other -expansions take place or the command gets executed. +Immediately before execution, each command is saved in the history list, +the size of which is controlled by the tt(HISTSIZE) parameter. The one +most recent command is always retained in any case. Each saved command in +the history list is called a history em(event) and is assigned a number, +beginning with 1 (one) when the shell starts up. The history number that +you may see in your prompt (see +ifzman(Prompt Expansion in zmanref(zshmisc))\ +ifnzman(noderef(Prompt Expansion))\ +) is the number that is to be assigned to the em(next) command. + startmenu() +menu(Overview) menu(Event Designators) menu(Word Designators) menu(Modifiers) endmenu() -texinode(Event Designators)(Word Designators)()(History Expansion) +texinode(Overview)(Event Designators)()(History Expansion) +subsect(Overview) +vindex(histchars, use of) +A history expansion begins with the first character of the tt(histchars) +parameter, which is `tt(!)' by default, and may occur anywhere on the +command line; history expansions do not nest. The `tt(!)' can be escaped +with `tt(\)' or can be enclosed between a pair of single quotes (tt('')) +to suppress its special meaning. Double quotes will em(not) work for +this. Following this history character is an optional event designator +(ifzman(see )noderef(Event Designators)) and then an optional word +designator (noderef(Word Designators)); if neither of these designators is +present, no history expansion occurs. + +Input lines containing history expansions are echoed after being expanded, +but before any other expansions take place and before the command is +executed. It is this expanded form that is recorded as the history event +for later references. + +By default, a history reference with no event designator refers to the +same event as any preceding history reference on that command line; if it +is the only history reference in a command, it refers to the previous +command. +pindex(CSH_JUNKIE_HISTORY, use of) +However, if the option tt(CSH_JUNKIE_HISTORY) is set, then every history +reference with no event specification em(always) refers to the previous +command. + +For example, `tt(!)' is the event designator for the previous command, so +`tt(!!:1)' always refers to the first word of the previous command, and +`tt(!!$)' always refers to the last word of the previous command. With +tt(CSH_JUNKIE_HISTORY) set, then `tt(!:1)' and `tt(!$)' function in the +same manner as `tt(!!:1)' and `tt(!!$)', respectively. Conversely, if +tt(CSH_JUNKIE_HISTORY) is unset, then `tt(!:1)' and `tt(!$)' refer to the +first and last words, respectively, of the same event referenced by the +nearest other history reference preceding them on the current command +line, or to the previous command if there is no preceding reference. + +The character sequence `tt(^)var(foo)tt(^)var(bar)' (where `tt(^)' is +actually the second character of the tt(histchars) parameter) +repeats the last command, replacing the string var(foo) with var(bar). +More precisely, the sequence `tt(^)var(foo)tt(^)var(bar)tt(^)' is +synonymous with `tt(!!:s)tt(^)var(foo)tt(^)var(bar)tt(^)', hence other +modifiers (see noderef(Modifiers)) may follow the final `tt(^)'. + +If the shell encounters the character sequence `tt(!")' +in the input, the history mechanism is temporarily disabled until +the current list (see +ifzman(zmanref(zshmisc))\ +ifnzman(noderef(Shell Grammar))\ +) is fully parsed. The `tt(!")' is removed from the input, and any +subsequent `tt(!)' characters have no special significance. + +findex(fc, use of) +A less convenient but more comprehensible form of command history support +is provided by the tt(fc) builtin. +texinode(Event Designators)(Word Designators)(Overview)(History Expansion) subsect(Event Designators) cindex(history event designators) cindex(event designators, history) -An event designator is a reference to a command-line entry in -the history list. +An event designator is a reference to a command-line entry in the history +list. In the list below, remember that the initial tt(`!') in each item +may be changed to another character by setting the tt(histchars) +parameter. startitem() item(tt(!))( Start a history expansion, except when followed by a blank, newline, -`tt(=)' or `tt(LPAR())'. +`tt(=)' or `tt(LPAR())'. If followed immediately by a word designator +(ifzman(see )noderef(Word Designators)), this forms a history reference +with no event designator (ifzman(see )noderef(Overview)). ) item(tt(!!))( Refer to the previous command. @@ -95,7 +160,9 @@ item(tt(!)var(str))( Refer to the most recent command starting with var(str). ) item(tt(!?)var(str)[tt(?)])( -Refer to the most recent command containing var(str). +Refer to the most recent command containing var(str). The trailing +`tt(?)' is necessary if this reference is to be followed by a modifier or +followed by any text that is not to be considered part of var(str). ) item(tt(!#))( Refer to the current command line typed in so far. The line is @@ -110,10 +177,10 @@ texinode(Word Designators)(Modifiers)(Event Designators)(History Expansion) subsect(Word Designators) cindex(history word designators) cindex(word designators, history) -A word designator indicates which word or words of a given command line will -be included in a history reference. A `tt(:)' +A word designator indicates which word or words of a given command line are +to be included in a history reference. A `tt(:)' usually separates the event specification from the word designator. -It can be omitted if the word designator begins with a +It may be omitted only if the word designator begins with a `tt(^)', `tt($)', `tt(*)', `tt(-)' or `tt(%)'. Word designators include: @@ -129,14 +196,17 @@ sitem(var(x)tt(*))(Abbreviates `var(x)tt(-$)'.) sitem(var(x)tt(-))(Like `var(x)tt(*)' but omitting word tt($).) endsitem() -Note that a `tt(%)' word designator will only work when used as -`tt(!%)', `tt(!:%)' or `tt(!?)var(str)tt(?:%)', -and only when used after a tt(!?) expansion. Anything else will result +Note that a `tt(%)' word designator works only when used in one of +`tt(!%)', `tt(!:%)' or `tt(!?)var(str)tt(?:%)', and only when used after a +tt(!?) expansion (possibly in an earlier command). Anything else results in an error, although the error may not be the most obvious one. texinode(Modifiers)()(Word Designators)(History Expansion) subsect(Modifiers) -cindex(modifiers, history) +cindex(modifiers) +cindex(colon modifiers) cindex(history modifiers) +cindex(globbing modifiers) +cindex(parameter modifiers) After the optional word designator, you can add a sequence of one or more of the following modifiers, each preceded by a `tt(:)'. These modifiers also work on the result @@ -145,16 +215,19 @@ noted. startitem() item(tt(h))( -Remove a trailing pathname component, leaving the head. +Remove a trailing pathname component, leaving the head. This works +like `tt(dirname)'. ) item(tt(r))( -Remove a trailing suffix of the form `tt(.)var(xxx)', leaving the basename. +Remove a filename extension of the form `tt(.)var(xxx)', leaving +the root name. ) item(tt(e))( -Remove all but the suffix. +Remove all but the extension. ) item(tt(t))( -Remove all leading pathname components, leaving the tail. +Remove all leading pathname components, leaving the tail. This works +like `tt(basename)'. ) item(tt(p))( Print the new command but do not execute it. Only works with history @@ -162,15 +235,16 @@ expansion. ) item(tt(q))( Quote the substituted words, escaping further substitutions. Works -with history expansion and parameter expansion, though in the second -case it is only useful if the resulting text is to be re-evaluated -such as by tt(eval). +with history expansion and parameter expansion, though for parameters +it is only useful if the resulting text is to be re-evaluated such as +by tt(eval). ) item(tt(Q))( Remove one level of quotes from the substituted words. ) item(tt(x))( -Like tt(q), but break into words at each blank. +Like tt(q), but break into words at whitespace. Does not work with +parameter expansion. ) item(tt(l))( Convert the words to all lowercase. @@ -178,30 +252,6 @@ Convert the words to all lowercase. item(tt(u))( Convert the words to all uppercase. ) -item(tt(f))( -(This and the following -tt(F), tt(w) and tt(W) modifier only work with parameter expansion and -filename generation.) -Repeats the immediately (without a colon) following modifier until the -resulting word doesn't change any more. -) -item(tt(F:)var(expr)tt(:))( -Like tt(f), but repeats only var(n) times if the expression -var(expr) evaluates to var(n). Any character can be used instead of -the `tt(:)'; if `tt(LPAR())', `tt([)', or `tt({)' -is used as the opening delimiter, -the closing delimiter should be 'tt(RPAR())', `tt(])', or `tt(})', -respectively. -) -item(tt(w))( -Makes the immediately following modifier work on each word in the -string. -) -item(tt(W:)var(sep)tt(:))( -Like tt(w) but words are considered to be the parts of the string -that are separated by var(sep). Any character can be used instead of -the `tt(:)'; opening parentheses are handled specially, see above. -) item(tt(s/)var(l)tt(/)var(r)[tt(/)])( Substitute var(r) for var(l) as described below. Unless preceded immediately by a tt(g), with no colon between, @@ -230,43 +280,33 @@ the rightmost `tt(?)' in a context scan can similarly be omitted. Note the same record of the last var(l) and var(r) is maintained across all forms of expansion. -By default, a history reference with no event specification refers to the same -line as the previous history reference on that command line, unless it is the -first history reference in a command. In that case, a history reference -with no event specification always refers to the previous command. However, -if the option tt(CSH_JUNKIE_HISTORY) is set, -pindex(CSH_JUNKIE_HISTORY, use of) -then history reference with no -event specification will em(always) refer to the previous command. - -For example, `tt(!!:1)' -will always refer to the first word of the previous command, and `tt(!!$)' -will always refer to the last word of the previous command. And with -tt(CSH_JUNKIE_HISTORY) set, then `tt(!:1)' and `tt(!$)' -will function in the same manner as `tt(!!:1)' and `tt(!!$)', -respectively. However, if tt(CSH_JUNKIE_HISTORY) is unset, then -`tt(!:1)' and `tt(!$)' -will refer to the first and last words respectively, of the last command -referenced on the current command line. However, if they are the first history -reference on the command line, then they refer to the previous command. +The following tt(f), tt(F), tt(w) and tt(W) modifiers work only with +parameter expansion and filename generation. They are listed here to +provide a single point of reference for all modifiers. -The character sequence `tt(^)var(foo)tt(^)var(bar)' (where `tt(^)' is -actually the second charcter of the tt(histchars) parameter) -repeats the last command, replacing the string var(foo) with var(bar). -More precisely, the sequence `tt(^)var(foo)tt(^)var(bar)tt(^)' is -synonymous with `tt(!!:s)tt(^)var(foo)tt(^)var(bar)tt(^)', hence other -modifiers may follow the final `tt(^)'. - -If the shell encounters the character sequence `tt(!")' -in the input, the history mechanism is temporarily disabled until -the current list is fully parsed. The `tt(!")' -is removed from the input, and any subsequent `tt(!)' -characters have no special significance. - -A less convenient but more comprehensible -form of command history support -is provided by the tt(fc) builtin. -findex(fc, use of) +startitem() +item(tt(f))( +Repeats the immediately (without a colon) following modifier until the +resulting word doesn't change any more. +) +item(tt(F:)var(expr)tt(:))( +Like tt(f), but repeats only var(n) times if the expression +var(expr) evaluates to var(n). Any character can be used instead of +the `tt(:)'; if `tt(LPAR())', `tt([)', or `tt({)' +is used as the opening delimiter, +the closing delimiter should be 'tt(RPAR())', `tt(])', or `tt(})', +respectively. +) +item(tt(w))( +Makes the immediately following modifier work on each word in the +string. +) +item(tt(W:)var(sep)tt(:))( +Like tt(w) but words are considered to be the parts of the string +that are separated by var(sep). Any character can be used instead of +the `tt(:)'; opening parentheses are handled specially, see above. +) +enditem() texinode(Process Substitution)(Parameter Expansion)(History Expansion)(Expansion) sect(Process Substitution) cindex(process substitution) @@ -276,38 +316,71 @@ Each command argument of the form `tt(>LPAR())var(list)tt(RPAR())' or `tt(=LPAR())var(list)tt(RPAR())' is subject to process substitution. -In the case of the tt(<) or tt(>) forms, the shell will run process -var(list) asynchronously, connected to a named pipe (FIFO). -The name of this pipe will become the argument to the command. -If the form with tt(>) -is selected then writing on this file will provide input for var(list). -If tt(<) is used, then the file passed as an argument will -be a named pipe connected to the output of the var(list) process. -For example, - -nofill(tt(paste <LPAR()cut -f1) var(file1)tt(RPAR() <LPAR()cut -f3) var(file2)tt(RPAR() | +In the case of the tt(<) or tt(>) forms, the shell runs process +var(list) asynchronously. If the system supports the tt(/dev/fd) +mechanism, the command argument is the name of the device file +corresponding to a file descriptor; otherwise, if the system supports named +pipes (FIFOs), the command argument will be a named pipe. If the form with +tt(>) is selected then writing on this special file will provide input for +var(list). If tt(<) is used, then the file passed as an argument will +be connected to the output of the var(list) process. For example, + +example(tt(paste <LPAR()cut -f1) var(file1)tt(RPAR() <LPAR()cut -f3) var(file2)tt(RPAR() | tee >LPAR())var(process1)tt(RPAR() >LPAR())var(process2)tt(RPAR() >/dev/null)) cuts fields 1 and 3 from the files var(file1) and var(file2) respectively, pastes the results together, and sends it to the processes var(process1) and var(process2). -Note that the file, which is passed as an argument to the command, -is a system pipe, so programs that expect to lseek (see manref(lseek)(2)) -on the file will not work. + +If tt(=LPAR())var(...)tt(RPAR()) is used instead of +tt(<LPAR())var(...)tt(RPAR()), +then the file passed as an argument will be the name +of a temporary file containing the output of the var(list) +process. This may be used instead of the tt(<) +form for a program that expects to lseek (see manref(lseek)(2)) +on the input file. + +The tt(=) form is useful as both the tt(/dev/fd) and the named pipe +implementation of tt(<LPAR())var(...)tt(RPAR()) have drawbacks. In +the former case, some programmes may automatically close the file +descriptor in question before examining the file on the command line, +particularly if this is necessary for security reasons such as when the +programme is running setuid. In the second case, if the +programme does not actually open the file, the subshell attempting to read +from or write to the pipe will (in a typical implementation, different +operating systems may have different behaviour) block for ever and have to +be killed explicitly. In both cases, the shell actually supplies the +information using a pipe, so that programmes that expect to lseek +(see manref(lseek)(2)) on the file will not work. + Also note that the previous example can be more compactly and efficiently written (provided the tt(MULTIOS) option is set) as: -nofill(tt(paste <LPAR()cut -f1) var(file1)tt(RPAR() <LPAR()cut -f3) var(file2)tt(RPAR() > >LPAR())var(process1)tt(RPAR() > >LPAR())var(process2)tt(RPAR())) +example(tt(paste <LPAR()cut -f1) var(file1)tt(RPAR() <LPAR()cut -f3) var(file2)tt(RPAR()) ifzman(\ +)tt(> >LPAR())var(process1)tt(RPAR() > >LPAR())var(process2)tt(RPAR())) The shell uses pipes instead of FIFOs to implement the latter two process substitutions in the above example. -If tt(=) is used, -then the file passed as an argument will be the name -of a temporary file containing the output of the var(list) -process. This may be used instead of the tt(<) -form for a program that expects to lseek (see manref(lseek)(2)) -on the input file. +There is an additional problem with tt(>LPAR())var(process)tt(RPAR()); when +this is attached to an external command, the parent shell does not wait +for var(process) to finish and hence an immediately following command +cannot rely on the results being complete. The problem and solution are +the same as described in the section em(MULTIOS) in +ifzman(zmanref(zshmisc))\ +ifnzman(noderef(Redirection)). Hence in a simplified +version of the example above: + +example(tt(paste <LPAR()cut -f1) var(file1)tt(RPAR() <LPAR()cut -f3) var(file2)tt(RPAR()) tt(> >LPAR())var(process)tt(RPAR())) + +(note that no tt(MULTIOS) are involved), var(process) will be run +asynchronously. The workaround is: + +example(tt({ paste <LPAR()cut -f1) var(file1)tt(RPAR() <LPAR()cut -f3) var(file2)tt(RPAR() }) tt(> >LPAR())var(process)tt(RPAR())) + +The extra processes here are +spawned from the parent shell which will wait for their completion. + texinode(Parameter Expansion)(Command Substitution)(Process Substitution)(Expansion) sect(Parameter Expansion) cindex(parameter expansion) @@ -323,12 +396,17 @@ noderef(Parameters) for a description of parameters, including arrays, associative arrays, and subscript notation to access individual array elements. +Note in particular the fact that words of unquoted parameters are not +automatically split on whitespace unless the option tt(SH_WORD_SPLIT) is +set; see references to this option below for more details. This is an +important difference from other shells. + In the expansions discussed below that require a pattern, the form of the pattern is the same as that used for filename generation; see noderef(Filename Generation). Note that these patterns, along with the replacement text of any substitutions, are themselves subject to parameter expansion, command substitution, and arithmetic expansion. -In addition to the following operations, the file modifiers described in +In addition to the following operations, the colon modifiers described in noderef(Modifiers) in noderef(History Expansion) can be applied: for example, tt(${i:s/foo/bar/}) performs string substitution on the expansion of parameter tt($i). @@ -422,13 +500,21 @@ item(tt(${)var(name)tt(//)var(pattern)tt(/)var(repl)tt(}))( Replace the longest possible match of var(pattern) in the expansion of parameter var(name) by string var(repl). The first form replaces just the first occurrence, the second form all occurrences. +Both var(pattern) and var(repl) are subject to double-quoted substitution, +so that expressions like tt(${name/$opat/$npat}) will work, but note the +usual rule that pattern characters in tt($opat) are not treated specially +unless either the option tt(GLOB_SUBST) is set, or tt($opat) is instead +substituted as tt(${~opat}). + The var(pattern) may begin with a `tt(#)', in which case the var(pattern) must match at the start of the string, or `tt(%)', in which case it must match at the end of the string. The var(repl) may be an empty string, in which case the final `tt(/)' may also be omitted. -To quote the final `tt(/)' in other cases it should be preceded by two -backslashes (i.e., a quoted backslash); this is not necessary if the -`tt(/)' occurs inside a substituted parameter. +To quote the final `tt(/)' in other cases it should be preceded by a +single backslash; this is not necessary if the +`tt(/)' occurs inside a substituted parameter. Note also that the `tt(#)' +and `tt(%)' are not active if they occur inside a substituted parameter, +even at the start. The first `tt(/)' may be preceded by a `tt(:)', in which case the match will only succeed if it matches the entire word. Note also the @@ -456,7 +542,7 @@ Note that `tt(^)', `tt(=)', and `tt(~)', below, must appear to the left of `tt(#)' when these forms are combined. ) item(tt(${^)var(spec)tt(}))( -pindex(RC_EXPAND_PARAM, use of) +pindex(RC_EXPAND_PARAM, toggle) cindex(array expansion style, rc) cindex(rc, array expansion style) Turn on the tt(RC_EXPAND_PARAM) option for the @@ -477,9 +563,9 @@ tt($var[)var(N)tt(]) may themselves be split into different list elements. ) item(tt(${=)var(spec)tt(}))( -pindex(SH_WORD_SPLIT, use of) -cindex(field splitting, sh style) -cindex(sh, field splitting style) +pindex(SH_WORD_SPLIT, toggle) +cindex(field splitting, sh style, parameter) +cindex(sh, field splitting style, parameter) Perform word splitting using the rules for tt(SH_WORD_SPLIT) during the evaluation of var(spec), but regardless of whether the parameter appears in double quotes; if the `tt(=)' is doubled, turn it off. @@ -493,7 +579,7 @@ of var(spec) em(before) the assignment to var(name) is performed. This affects the result of array assignments with the tt(A) flag. ) item(tt(${~)var(spec)tt(}))( -pindex(GLOB_SUBST) +pindex(GLOB_SUBST, toggle) Turn on the tt(GLOB_SUBST) option for the evaluation of var(spec); if the `tt(~)' is doubled, turn it off. When this option is set, the string resulting from the expansion will be interpreted as a @@ -511,11 +597,15 @@ possible to perform nested operations: tt(${${foo#head}%tail}) substitutes the value of tt($foo) with both `tt(head)' and `tt(tail)' deleted. The form with tt($LPAR())...tt(RPAR()) is often useful in combination with the flags described next; see the examples below. +Each var(name) or nested tt(${)...tt(}) in a parameter expansion may +also be followed by a subscript expression as described in +ifzman(em(Array Parameters) in zmanref(zshparam))\ +ifnzman(noderef(Array Parameters)). -Note that double quotes may appear around nested substitutions, in which +Note that double quotes may appear around nested expressions, in which case only the part inside is treated as quoted; for example, tt(${(f)"$(foo)"}) quotes the result of tt($(foo)), but the flag `tt((f))' -(see below) is applied using the rules for unquoted substitutions. Note +(see below) is applied using the rules for unquoted expansions. Note further that quotes are themselves nested in this context; for example, in tt("${(@f)"$(foo)"}"), there are two sets of quotes, one surrounding the whole expression, the other (redundant) surrounding the tt($(foo)) as @@ -527,95 +617,65 @@ cindex(flags, parameter expansion) cindex(substitution, parameter, flags) If the opening brace is directly followed by an opening parenthesis, the string up to the matching closing parenthesis will be taken as a -list of flags. Where arguments are valid, any character, or the -matching pairs `tt(LPAR())...tt(RPAR())', `tt({)...tt(})', -`tt([)...tt(])', or `tt(<)...tt(>)', may be used -in place of the colon as delimiters. The following flags are supported: +list of flags. In cases where repeating a flag is meaningful, the +repetitions need not be consecutive; for example, `(tt(q%q%q))' +means the same thing as the more readable `(tt(%%qqq))'. The +following flags are supported: startitem() -item(tt(A))( -Create an array parameter with tt(${)...tt(=)...tt(}), -tt(${)...tt(:=)...tt(}) or tt(${)...tt(::=)...tt(}). -If this flag is repeated (as in tt(AA)), create an associative -array parameter. Assignment is made before sorting or padding. -The var(name) part may be a subscripted range for ordinary -arrays; the var(word) part em(must) be converted to an array, for -example by using tt(${(AA)=)var(name)tt(=)...tt(}) to activate word -splitting, when creating an associative array. +item(tt(%))( +Expand all tt(%) escapes in the resulting words in the same way as in in +prompts (see noderef(Prompt Expansion)). If this flag is given twice, +full prompt expansion is done on the resulting words, depending on the +setting of the tt(PROMPT_PERCENT), tt(PROMPT_SUBST) and tt(PROMPT_BANG) +options. ) item(tt(@))( In double quotes, array elements are put into separate words. -E.g., tt("${(@)foo}") is equivalent to tt("${foo[@]}") and -tt("${(@)foo[1,2]}") is the same as tt("$foo[1]" "$foo[2]"). -) -item(tt(e))( -Perform em(parameter expansion), em(command substitution) and -em(arithmetic expansion) on the result. Such expansions can be -nested but too deep recursion may have unpredictable effects. -) -item(tt(P))( -This forces the value of the parameter var(name) to be interpreted as a -further parameter name, whose value will be used where appropriate. If used -with a nested parameter or command substitution, the result of that will be -taken as a parameter name in the same way. For example, if you have -`tt(foo=bar)' and `tt(bar=baz)', the strings tt(${(P)foo}), -tt(${(P)${foo}}), and tt(${(P)$(echo bar)}) will be expanded to `tt(baz)'. -) -item(tt(o))( -Sort the resulting words in ascending order. +E.g., `tt("${(@)foo}")' is equivalent to `tt("${foo[@]}")' and +`tt("${(@)foo[1,2]}")' is the same as `tt("$foo[1]" "$foo[2]")'. +This is distinct from em(field splitting) by the the tt(f), tt(s) +or tt(z) flags, which still applies within each array element. ) -item(tt(O))( -Sort the resulting words in descending order. -) -item(tt(i))( -With tt(o) or tt(O), sort case-independently. +item(tt(A))( +Create an array parameter with `tt(${)...tt(=)...tt(})', +`tt(${)...tt(:=)...tt(})' or `tt(${)...tt(::=)...tt(})'. +If this flag is repeated (as in `tt(AA)'), create an associative +array parameter. Assignment is made before sorting or padding. +The var(name) part may be a subscripted range for ordinary +arrays; the var(word) part em(must) be converted to an array, for +example by using `tt(${(AA)=)var(name)tt(=)...tt(})' to activate +field splitting, when creating an associative array. ) -item(tt(L))( -Convert all letters in the result to lower case. +item(tt(a))( +With tt(o) or tt(O), sort in array index order. Note that `tt(oa)' is +therefore equivalent to the default but `tt(Oa)' is useful for +obtaining an array's elements in reverse order. ) -item(tt(U))( -Convert all letters in the result to upper case. +item(tt(c))( +With tt(${#)var(name)tt(}), count the total number of characters in an array, +as if the elements were concatenated with spaces between them. ) item(tt(C))( Capitalize the resulting words. `Words' in this case refers to sequences of alphanumeric characters separated by non-alphanumerics, em(not) to words that result from field splitting. ) -item(tt(V))( -Make any special characters in the resulting words visible. -) -item(tt(q))( -Quote the resulting words with backslashes. If this flag is given -twice, the resulting words are quoted in single quotes and if it is -given three times, the words are quoted in double quotes. If it is -given four times, the words are quoted in single quotes preceded a tt($). -) -item(tt(Q))( -Remove one level of quotes from the resulting words. -) -item(tt(%))( -Expand all tt(%) escapes in the resulting words in the same way as in -prompts (see noderef(Prompt Expansion)). If this flag is given twice, -full prompt expansion is done on the resulting words, depending on the -setting of the tt(PROMPT_PERCENT), tt(PROMPT_SUBST) and -tt(PROMPT_BANG) options. -) -item(tt(X))( -With this flag parsing errors occuring with the tt(Q) flag or the -pattern matching forms such as `tt(${)var(name)tt(#)var(pattern)tt(})' -are reported. Without the flag they are silently ignored. +item(tt(e))( +Perform em(parameter expansion), em(command substitution) and +em(arithmetic expansion) on the result. Such expansions can be +nested but too deep recursion may have unpredictable effects. ) -item(tt(c))( -With tt(${#)var(name)tt(}), count the total number of characters in an array, -as if the elements were concatenated with spaces between them. +item(tt(f))( +Split the result of the expansion to lines. This is a shorthand +for `tt(ps:\n:)'. ) -item(tt(w))( -With tt(${#)var(name)tt(}), count words in arrays or strings; the tt(s) -flag may be used to set a word delimiter. +item(tt(F))( +Join the words of arrays together using newline as a separator. +This is a shorthand for `tt(pj:\n:)'. ) -item(tt(W))( -Similar to tt(w) with the difference that empty words between -repeated delimiters are also counted. +item(tt(i))( +With tt(o) or tt(O), sort case-independently. ) item(tt(k))( If var(name) refers to an associative array, substitute the em(keys) @@ -624,54 +684,42 @@ subscripts (including ordinary arrays), force indices or keys to be substituted even if the subscript form refers to values. However, this flag may not be combined with subscript ranges. ) -item(tt(v))( -Used with tt(k), substitute (as two consecutive words) both the key -and the value of each associative array element. Used with subscripts, -force values to be substituted even if the subscript form refers to -indices or keys. -) -item(tt(p))( -Recognize the same escape sequences as the tt(print) builtin -in string arguments to any of the flags described below. +item(tt(L))( +Convert all letters in the result to lower case. ) -item(tt(l:)var(expr)tt(::)var(string1)tt(::)var(string2)tt(:))( -Pad the resulting words on the left. Each word will be truncated if -required and placed in a field var(expr) characters wide. The space -to the left will be filled with var(string1) (concatenated as often -as needed) or spaces if var(string1) is not given. If both -var(string1) and var(string2) are given, this string is inserted -once directly to the left of each word, before padding. +item(tt(n))( +With tt(o) or tt(O), sort numerically. ) -item(tt(r:)var(expr)tt(::)var(string1)tt(::)var(string2)tt(:))( -As tt(l), but pad the words on the right and insert var(string2) -on the right. +item(tt(o))( +Sort the resulting words in ascending order. ) -item(tt(j:)var(string)tt(:))( -Join the words of arrays together using var(string) as a separator. -pindex(SH_WORD_SPLIT, use of) -Note that this occurs before field splitting by the tt(SH_WORD_SPLIT) -option. +item(tt(O))( +Sort the resulting words in descending order. ) -item(tt(F))( -Join the words of arrays together using newline as a separator. -This is a shorthand for `tt(pj:\n:)'. +item(tt(P))( +This forces the value of the parameter var(name) to be interpreted as a +further parameter name, whose value will be used where appropriate. If +used with a nested parameter or command substitution, the result of that +will be taken as a parameter name in the same way. For example, if you +have `tt(foo=bar)' and `tt(bar=baz)', the strings tt(${(P)foo}), +tt(${(P)${foo}}), and tt(${(P)$(echo bar)}) will be expanded to `tt(baz)'. ) -item(tt(s:)var(string)tt(:))( -Force field splitting (see the option tt(SH_WORD_SPLIT)) at the -separator var(string). Splitting only occurs in places where an -array value is valid. +item(tt(q))( +Quote the resulting words with backslashes. If this flag is given +twice, the resulting words are quoted in single quotes and if it is +given three times, the words are quoted in double quotes. If it is +given four times, the words are quoted in single quotes preceded by a tt($). ) -item(tt(f))( -Split the result of the expansion to lines. This is a shorthand -for `tt(ps:\n:)'. +item(tt(Q))( +Remove one level of quotes from the resulting words. ) item(tt(t))( Use a string describing the type of the parameter where the value of the parameter would usually appear. This string consists of keywords separated by hyphens (`tt(-)'). The first keyword in the string describes the main type, it can be one of `tt(scalar)', `tt(array)', `tt(integer)', -or `tt(association)'. The other keywords describe the type in more -detail: +`tt(float)' or `tt(association)'. The other keywords describe the type in +more detail: startitem() item(tt(local))( @@ -714,6 +762,80 @@ for special parameters defined by the shell ) enditem() ) +item(tt(u))( +Expand only the first occurrence of each unique word. +) +item(tt(U))( +Convert all letters in the result to upper case. +) +item(tt(v))( +Used with tt(k), substitute (as two consecutive words) both the key +and the value of each associative array element. Used with subscripts, +force values to be substituted even if the subscript form refers to +indices or keys. +) +item(tt(V))( +Make any special characters in the resulting words visible. +) +item(tt(w))( +With tt(${#)var(name)tt(}), count words in arrays or strings; the tt(s) +flag may be used to set a word delimiter. +) +item(tt(W))( +Similar to tt(w) with the difference that empty words between +repeated delimiters are also counted. +) +item(tt(X))( +With this flag parsing errors occurring with the tt(Q) and tt(e) flags or the +pattern matching forms such as `tt(${)var(name)tt(#)var(pattern)tt(})' +are reported. Without the flag they are silently ignored. +) +item(tt(z))( +Split the result of the expansion into words using shell parsing to +find the words, i.e. taking into account any quoting in the value. + +Note that this is done very late, as for the `tt((s))' flag. So to +access single words in the result, one has to use nested expansions as +in `tt(${${(z)foo}[2]})'. Likewise, to remove the quotes in the +resulting words one would do: `tt(${(Q)${(z)foo}})'. +) +enditem() + +The following flags (except tt(p)) are followed by one or more arguments +as shown. Any character, or the matching pairs `tt(LPAR())...tt(RPAR())', +`tt({)...tt(})', `tt([)...tt(])', or `tt(<)...tt(>)', may be used in place +of a colon as delimiters, but note that when a flag takes more than one +argument, a matched pair of delimiters must surround each argument. + +startitem() +item(tt(p))( +Recognize the same escape sequences as the tt(print) builtin +in string arguments to any of the flags described below. +) +item(tt(j:)var(string)tt(:))( +Join the words of arrays together using var(string) as a separator. +pindex(SH_WORD_SPLIT, use of) +Note that this occurs before field splitting by the tt(SH_WORD_SPLIT) +option. +) +item(tt(l:)var(expr)tt(::)var(string1)tt(::)var(string2)tt(:))( +Pad the resulting words on the left. Each word will be truncated if +required and placed in a field var(expr) characters wide. The space +to the left will be filled with var(string1) (concatenated as often +as needed) or spaces if var(string1) is not given. If both +var(string1) and var(string2) are given, this string is inserted +once directly to the left of each word, before padding. +) +item(tt(r:)var(expr)tt(::)var(string1)tt(::)var(string2)tt(:))( +As tt(l), but pad the words on the right and insert var(string2) +on the right. +) +item(tt(s:)var(string)tt(:))( +Force field splitting (see the option tt(SH_WORD_SPLIT)) at the +separator var(string). Note that a var(string) of two or more +characters means all must all match in sequence; this differs from +the treatment of two or more characters in the tt(IFS) parameter. +) enditem() The following flags are meaningful with the tt(${)...tt(#)...tt(}) or @@ -725,24 +847,34 @@ item(tt(S))( Search substrings as well as beginnings or ends; with tt(#) start from the beginning and with tt(%) start from the end of the string. With substitution via tt(${)...tt(/)...tt(}) or -tt(${)...tt(//)...tt(}), specifies that the shortest instead of the -longest match should be replaced. +tt(${)...tt(//)...tt(}), specifies non-greedy matching, i.e. that the +shortest instead of the longest match should be replaced. ) item(tt(I:)var(expr)tt(:))( Search the var(expr)th match (where var(expr) evaluates to a number). This only applies when searching for substrings, either with the tt(S) flag, or with tt(${)...tt(/)...tt(}) (only the var(expr)th match is substituted) or tt(${)...tt(//)...tt(}) (all matches from the -var(expr)th on are substituted). The var(expr)th match is counted -such that there is either one or zero matches from each starting -position in the string, although for global substitution matches -overlapping previous replacements are ignored. -) -item(tt(M))( -Include the matched portion in the result. -) -item(tt(R))( -Include the unmatched portion in the result (the em(R)est). +var(expr)th on are substituted). The default is to take the first match. + +The var(expr)th match is counted such that there is either one or zero +matches from each starting position in the string, although for global +substitution matches overlapping previous replacements are ignored. With +the tt(${)...tt(%)...tt(}) and tt(${)...tt(%%)...tt(}) forms, the starting +position for the match moves backwards from the end as the index increases, +while with the other forms it moves forward from the start. + +Hence with the string +example(which switch is the right switch for Ipswich?) +substitutions of the form +tt(${)LPAR()tt(SI:)var(N)tt(:)RPAR()tt(string#w*ch}) as var(N) increases +from 1 will match and remove `tt(which)', `tt(witch)', `tt(witch)' and +`tt(wich)'; the form using `tt(##)' will match and remove `tt(which switch +is the right switch for Ipswich)', `tt(witch is the right switch for +Ipswich)', `tt(witch for Ipswich)' and `tt(wich)'. The form using `tt(%)' +will remove the same matches as for `tt(#)', but in reverse order, and the +form using `tt(%%)' will remove the same matches as for `tt(##)' in reverse +order. ) item(tt(B))( Include the index of the beginning of the match in the result. @@ -750,9 +882,15 @@ Include the index of the beginning of the match in the result. item(tt(E))( Include the index of the end of the match in the result. ) +item(tt(M))( +Include the matched portion in the result. +) item(tt(N))( Include the length of the match in the result. ) +item(tt(R))( +Include the unmatched portion in the result (the em(R)est). +) enditem() subsect(Rules) @@ -824,7 +962,7 @@ Note that the `tt((F))' flag implicitly supplies a string for joining in this manner. ) item(tt(8.) em(Forced Splitting))( -If one of the `tt((s))' or `tt((f))' flags are present, or the `tt(=)' +If one of the `tt((s))', `tt((f))' or `tt((z))' flags are present, or the `tt(=)' specifier was present (e.g. tt(${=)var(var)tt(})), the word is split on occurrences of the specified string, or (for tt(=) with neither of the two flags present) any of the characters in tt($IFS). @@ -833,17 +971,34 @@ item(tt(9.) em(Shell Word Splitting))( If no `tt((s))', `tt((f))' or `tt(=)' was given, but the word is not quoted and the option tt(SH_WORD_SPLIT) is set, the word is split on occurrences of any of the characters in tt($IFS). Note this step, too, -take place at all levels of a nested substitution. +takes place at all levels of a nested substitution. ) -item(tt(10.) em(Re-Evaluation))( +item(tt(10.) em(Uniqueness))( +If the result is an array and the `tt((u))' flag was present, duplicate +elements are removed from the array. +) +item(tt(11.) em(Ordering))( +If the result is still an array and one of the `tt((o))' or `tt((O))' flags +was present, the array is reordered. +) +item(tt(12.) em(Re-Evaluation))( Any `tt((e))' flag is applied to the value, forcing it to be re-examined for new parameter substitutions, but also for command and arithmetic substitutions. ) -item(tt(11.) em(Padding))( +item(tt(13.) em(Padding))( Any padding of the value by the `tt(LPAR()l.)var(fill)tt(.RPAR())' or `tt(LPAR()r.)var(fill)tt(.RPAR())' flags is applied. ) +item(tt(14.) em(Semantic Joining))( +In contexts where expansion semantics requires a single word to +result, all words are rejoined with the first character of tt(IFS) +between. So in `tt(${LPAR()P)tt(RPAR()${LPAR()f)tt(RPAR()lines}})' +the value of tt(${lines}) is split at newlines, but then must be +joined again before the tt(P) flag can be applied. + +If a single word is not required, this rule is skipped. +) enditem() subsect(Examples) @@ -867,7 +1022,7 @@ that this is a scalar, so that (despite the `tt((@))' flag) the subscript picks the first character. ) item(tt("${${(@)foo}[1]}"))( -The produces the result `tt(bar)'. In this case, the inner substitution +This produces the result `tt(bar)'. In this case, the inner substitution tt("${(@)foo}") produces the array `tt(LPAR()bar baz)tt(RPAR())'. The outer substitution tt("${...[1]}") detects that this is an array and picks the first word. This is similar to the simple case tt("${foo[1]}"). @@ -1006,11 +1161,9 @@ tt($OLDPWD) are never abbreviated in this fashion. If a word begins with an unquoted `tt(=)' and the tt(EQUALS) option is set, the remainder of the word is taken as the -name of a command or alias. If a command +name of a command. If a command exists by that name, the word is replaced by the full pathname of the command. -If an alias exists by that name, the word -is replaced with the text of the alias. Filename expansion is performed on the right hand side of a parameter assignment, including those appearing after commands of the @@ -1028,7 +1181,6 @@ first `tt(=)' also inhibits this. texinode(Filename Generation)()(Filename Expansion)(Expansion) sect(Filename Generation) cindex(filename generation) -cindex(globbing) If a word contains an unquoted instance of one of the characters `tt(*)', `tt(LPAR())', `tt(|)', `tt(<)', `tt([)', or `tt(?)', it is regarded as a pattern for filename generation, unless the tt(GLOB) option is unset. @@ -1068,9 +1220,11 @@ Matches any of the enclosed characters. Ranges of characters can be specified by separating two characters by a `tt(-)'. A `tt(-)' or `tt(])' may be matched by including it as the first character in the list. +cindex(character classes) There are also several named classes of characters, in the form `tt([:)var(name)tt(:])' with the following meanings: `tt([:alnum:])' alphanumeric, `tt([:alpha:])' alphabetic, +`tt([:ascii:])' 7-bit, `tt([:blank:])' space or tab, `tt([:cntrl:])' control character, `tt([:digit:])' decimal digit, `tt([:graph:])' printable character except whitespace, @@ -1096,6 +1250,14 @@ Matches any number in the range var(x) to var(y), inclusive. Either of the numbers may be omitted to make the range open-ended; hence `tt(<->)' matches any number. To match individual digits, the tt([)...tt(]) form is more efficient. + +Be careful when using other wildcards adjacent to patterns of this form; +for example, tt(<0-9>*) will actually match any number whatsoever at the +start of the string, since the `tt(<0-9>)' will match the first digit, and +the `tt(*)' will match any others. This is a trap for the unwary, but is +in fact an inevitable consequence of the rule that the longest possible +match always succeeds. Expressions such as `tt(<0-9>[^[:digit:]]*)' can be +used instead. ) item(tt(LPAR())...tt(RPAR()))( Matches the enclosed pattern. This is used for grouping. @@ -1186,7 +1348,7 @@ The precedence of the operators given above is (highest) `tt(^)', `tt(/)', `tt(~)', `tt(|)' (lowest); the remaining operators are simply treated from left to right as part of a string, with `tt(#)' and `tt(##)' applying to the shortest possible -preceeding unit (i.e. a character, `tt(?)', `tt([)...tt(])', +preceding unit (i.e. a character, `tt(?)', `tt([)...tt(])', `tt(<)...tt(>)', or a parenthesised expression). As mentioned above, a `tt(/)' used as a directory separator may not appear inside parentheses, while a `tt(|)' must do so; in patterns used in other contexts @@ -1298,6 +1460,42 @@ item(tt(a)var(num))( Approximate matching: var(num) errors are allowed in the string matched by the pattern. The rules for this are described in the next subsection. ) +item(tt(s), tt(e))( +Unlike the other flags, these have only a local effect, and each must +appear on its own: `tt((#s))' and `tt((#e))' are the only valid forms. +The `tt((#s))' flag succeeds only at the start of the test string, and the +`tt((#e))' flag succeeds only at the end of the test string; they +correspond to `tt(^)' and `tt($)' in standard regular expressions. They +are useful for matching path segments in patterns other than those in +filename generation (where path segments are in any case treated +separately). For example, `tt(*((#s)|/)test((#e)|/)*)' matches a path +segment `tt(test)' in any of the following strings: tt(test), +tt(test/at/start), tt(at/end/test), tt(in/test/middle). + +Another use is in parameter substitution; for example +`tt(${array/(#s)A*Z(#e)})' will remove only elements of an array which +match the complete pattern `tt(A*Z)'. There are other ways of performing +many operations of this type, however the combination of the substitution +operations `tt(/)' and `tt(//)' with the `tt((#s))' and `tt((#e))' flags +provides a single simple and memorable method. + +Note that assertions of the form `tt((^(#s)))' also work, i.e. match +anywhere except at the start of the string, although this actually means +`anything except a zero-length portion at the start of the string'; you +need to use `tt((""~(#s)))' to match a zero-length portion of the string +not at the start. +) +item(tt(q))( +A `tt(q)' and everything up to the closing parenthesis of the globbing +flags are ignored by the pattern matching code. This is intended to +support the use of glob qualifiers, see below. The result is that +the pattern `tt((#b)(*).c(#q.))' can be used both for globbing and for +matching against a string. In the former case, the `tt((#q.))' will be +treated as a glob qualifier and the `tt((#b))' will not be useful, while in +the latter case the `tt((#b))' is useful for backreferences and the +`tt((#q.))' will be ignored. Note that colon modifiers in the glob +qualifiers are also not applied in ordinary pattern matching. +) enditem() For example, the test string tt(fooxx) can be matched by the pattern @@ -1374,6 +1572,13 @@ crucial one for establishing whether to use approximation; for example, tt((#a1)abc(#a0)xyz) will not match tt(abcdxyz), because the error occurs at the `tt(x)', where approximation is turned off. +Entire path segments may be matched approximately, so that +`tt((#a1)/foo/d/is/available/at/the/bar)' allows one error in any path +segment. This is much less efficient than without the tt((#a1)), however, +since every directory in the path must be scanned for a possible +approximate match. It is best to place the tt((#a1)) after any path +segments which are known to be correct. + subsect(Recursive Globbing) A pathname component of the form `tt(LPAR())var(foo)tt(/RPAR()#)' matches a path consisting of zero or more directories @@ -1391,10 +1596,11 @@ or example(ls **/bar) does a recursive directory search for files named `tt(bar)' (potentially -including the file `tt(bar)' in the current directory), not following -symbolic links. To follow links, use `tt(***/)'. Neither of these can be -combined with other forms of globbing within the same filename segment; in -that case, the `tt(*)' operators revert to their usual effect. +including the file `tt(bar)' in the current directory). This form does not +follow symbolic links; the alternative form `tt(***/)' does, but is +otherwise identical. Neither of these can be combined with other forms of +globbing within the same path segment; in that case, the `tt(*)' +operators revert to their usual effect. subsect(Glob Qualifiers) cindex(globbing, qualifiers) cindex(qualifiers, globbing) @@ -1409,7 +1615,22 @@ containing no `tt(|)' or `tt(LPAR())' characters (or `tt(~)' if it is special) is taken as a set of glob qualifiers. A glob subexpression that would normally be taken as glob qualifiers, for example `tt((^x))', can be forced to be treated as part of -the glob pattern by doubling the parentheses, for example `tt(((^x)))'. +the glob pattern by doubling the parentheses, in this case producing +`tt(((^x)))'. + +If the option tt(EXTENDED_GLOB) is set, a different syntax for glob +qualifiers is available, namely `tt((#qx))' where tt(x) is any of the same +glob qualifiers used in the other format. The qualifiers must still appear +at the end of the pattern. However, with this syntax multiple glob +qualifiers may be chained together. They are treated as a logical AND of +the individual sets of flags. Also, as the syntax is unambiguous, the +expression will be treated as glob qualifiers just as long any parentheses +contained within it are balanced; appearance of `tt(|)', `tt(LPAR())' or +`tt(~)' does not negate the effect. Note that qualifiers will be +recognised in this form even if a bare glob qualifier exists at the end of +the pattern, for example `tt(*(#q*)(.))' will recognise executable regular +files if both options are set; however, mixed syntax should probably be +avoided for the sake of clarity. A qualifier may be any one of the following: @@ -1417,6 +1638,12 @@ startitem() item(tt(/))( directories ) +item(tt(F))( +`full' (i.e. non-empty) directories. Note that the +opposite sense tt(LPAR()^F)tt(RPAR()) expands to empty directories +and all non-directories. Use tt(LPAR()/^F)tt(RPAR()) for +empty directories +) item(tt(.))( plain files ) @@ -1494,11 +1721,11 @@ If the qualifier `tt(f)' is followed by any other character anything up to the next matching character (`tt([)', `tt({)', and `tt(<)' match `tt(])', `tt(})', and `tt(>)' respectively, any other character matches itself) is taken as a list of comma-separated -var(sub-spec)s. Each var(sub-spec) may be either a octal number as +var(sub-spec)s. Each var(sub-spec) may be either an octal number as described above or a list of any of the characters `tt(u)', `tt(g)', `tt(o)', and `tt(a)', followed by a `tt(=)', a `tt(PLUS())', or a `tt(-)', followed by a list of any of the characters `tt(r)', `tt(w)', -`tt(x)', `tt(s)', and `tt(t)', or a octal digit. The first list of +`tt(x)', `tt(s)', and `tt(t)', or an octal digit. The first list of characters specify which access rights are to be checked. If a `tt(u)' is given, those for the owner of the file are used, if a `tt(g)' is given, those of the group are checked, a `tt(o)' means to test those @@ -1520,30 +1747,50 @@ the owner and the other members of the group have at least write permission, and for which other users don't have read or execute permission. ) -item(tt(e)var(string))( -The var(string) will be executed and the return value determines if the -filename should be included in the list (if it is zero) or not (if it -is non-zero). The first character after the `tt(e)' will be used as a -separator and anything up to the next matching separator will be taken -as the var(string) (`tt([)', `tt({)', and `tt(<)' match `tt(])', -`tt(})', and `tt(>)' respectively, any other character matches -itself). Note that expansions have to be quoted in the var(string) to -prevent them from being expanded before globbing is done. - -During the execution of var(string) the parameter tt(REPLY) is set to -the filename currently being tested. It may also be set to any string -to make this string be inserted into the list instead of the original -filename. Also, the parameter tt(reply) may be set to an array or a -string and if it is, these strings will be inserted instead of the -value of the tt(REPLY) parameter. For security reasons, tt(reply) -will be unset by the shell before the var(string) is executed. +xitem(tt(e)var(string)) +item(tt(PLUS())var(cmd))( +The var(string) will be executed as shell code. The filename will be +included in the list if and only if the code returns a zero status (usually +the status of the last command). The first character after the `tt(e)' +will be used as a separator and anything up to the next matching separator +will be taken as the var(string); `tt([)', `tt({)', and `tt(<)' match +`tt(])', `tt(})', and `tt(>)', respectively, while any other character +matches itself. Note that expansions must be quoted in the var(string) +to prevent them from being expanded before globbing is done. + +vindex(REPLY, use of) +vindex(reply, use of) +During the execution of var(string) the filename currently being tested is +available in the parameter tt(REPLY); the parameter may be altered to +a string to be inserted into the list instead of the original +filename. In addition, the parameter tt(reply) may be set to an array or a +string, which overrides the value of tt(REPLY). If set to an array, the +latter is inserted into the command line word by word. + +For example, suppose a directory contains a single file `tt(lonely)'. Then +the expression `tt(*(e:'reply=(${REPLY}{1,2})':))' will cause the words +`tt(lonely1 lonely2)' to be inserted into the command line. Note the +quotation marks. + +The form tt(PLUS())var(cmd) has the same effect, but no delimiters appear +around var(cmd). Instead, var(cmd) is taken as the longest sequence of +characters following the tt(PLUS()) that are alphanumeric or underscore. +Typically var(cmd) will be the name of a shell function that contains the +appropriate test. For example, + +example(nt() { [[ $REPLY -nt $NTREF ]] } +NTREF=reffile +ls -l *(+nt)) + +lists all files in the directory that have been modified more recently than +tt(reffile). ) item(tt(d)var(dev))( files on the device var(dev) ) item(tt(l)[tt(-)|tt(PLUS())]var(ct))( files having a link count less than var(ct) (tt(-)), greater than -var(ct) (tt(PLUS())), or is equal to var(ct) +var(ct) (tt(PLUS())), or equal to var(ct) ) item(tt(U))( files owned by the effective user ID @@ -1618,19 +1865,24 @@ pindex(NUMERIC_GLOB_SORT, setting in pattern) ) item(tt(o)var(c))( specifies how the names of the files should be sorted. If var(c) is -tt(n) they are sorted by name (the default), if it is tt(L) they -are sorted depending on the size (length) of the files, if tt(l) -they are sorted by the number of links, and if tt(a), tt(m), and tt(c) +tt(n) they are sorted by name (the default); if it is tt(L) they +are sorted depending on the size (length) of the files; if tt(l) +they are sorted by the number of links; if tt(a), tt(m), or tt(c) they are sorted by the time of the last access, modification, or -inode change respectively. Note that tt(a), tt(m), and tt(c) compare -the age against the current time, hence the first name in the list is the -the youngest file. Also note that the modifiers tt(^) and tt(-) are -used, so `tt(*(^-oL))' gives a list of all files sorted by file size in -descending order, following any symbolic links. +inode change respectively; if tt(d), files in subdirectories appear before +those in the current directory at each level of the search --- this is best +combined with other criteria, for example `tt(odon)' to sort on names for +files within the same directory. Note that tt(a), tt(m), and tt(c) compare +the age against the current time, hence the first name in the list is the +youngest file. Also note that the modifiers tt(^) and tt(-) are used, +so `tt(*(^-oL))' gives a list of all files sorted by file size in descending +order, following any symbolic links. ) item(tt(O)var(c))( like `tt(o)', but sorts in descending order; i.e. `tt(*(^oc))' is the -same as `tt(*(Oc))' and `tt(*(^Oc))' is the same as `tt(*(oc))' +same as `tt(*(Oc))' and `tt(*(^Oc))' is the same as `tt(*(oc))'; `tt(Od)' +puts files in the current directory before those in subdirectories at each +level of the search. ) item(tt([)var(beg)[tt(,)var(end)]tt(]))( specifies which of the matched filenames should be included in the @@ -1644,7 +1896,11 @@ enditem() More than one of these lists can be combined, separated by commas. The whole list matches if at least one of the sublists matches (they are -`or'ed, the qualifiers in the sublists are `and'ed). +`or'ed, the qualifiers in the sublists are `and'ed). Some qualifiers, +however, affect all matches generated, independent of the sublist in +which they are given. These are the qualifiers `tt(M)', `tt(T)', +`tt(N)', `tt(D)', `tt(n)', `tt(o)', `tt(O)' and the subscripts given +in brackets (`tt([...])'). If a `tt(:)' appears in a qualifier list, the remainder of the expression in parenthesis is interpreted as a modifier (see noderef(Modifiers) @@ -1679,3 +1935,11 @@ example(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 tt(GLOB_DOTS) is explicitly switched off) except for tt(lex.c), tt(lex.h), tt(parse.c) and tt(parse.h). + +example(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 `tt(.)' is applied first, then the colon +modifiers in order from left to right. So if tt(EXTENDED_GLOB) is set and +the base pattern matches the regular file tt(builtin.pro), the shell will +print `tt(shmiltin.shmo)'. |