Justin Bishop
Justin Bishop

Reputation: 157

noglob function then use ls with param?

I just want to pass a glob through and then use it against ls directly. The simplest example would be:

test() { ls -d ~/$1 }
alias test="noglob test"
test D*

If I simply run ls D in my home directory: it outputs three files. but if I run the snippet provided, I get "/Users/jubi/D*": No such file or directory. What should I be doing? thanks!

Upvotes: 0

Views: 1501

Answers (1)

4ae1e1
4ae1e1

Reputation: 7634

The authoritative and complete documentation of Zsh expansion mechanism is located at http://zsh.sourceforge.net/Doc/Release/Expansion.html.

Here's the reason your version doesn't work:

If a word contains an unquoted instance of one of the characters ‘*’, ‘(’, ‘|’, ‘<’, ‘[’, or ‘?’, it is regarded as a pattern for filename generation, unless the GLOB option is unset.

emphasis mine. Your glob operator, generated by parameter expansion, isn't considered unquoted.

You need the GLOB_SUBST option to evaluate the parameter expansion result as a glob pattern. a setopt globsubst, unsetopt globsubst pair works, of course, but the easiest way is to use the following pattern specifically for this purpose:

${~spec}

Turn on the GLOB_SUBST option for the evaluation of spec; if the ‘~’ is doubled, turn it off. When this option is set, the string resulting from the expansion will be interpreted as a pattern anywhere that is possible, such as in filename expansion and filename generation and pattern-matching contexts like the right hand side of the ‘=’ and ‘!=’ operators in conditions.

In nested substitutions, note that the effect of the ~ applies to the result of the current level of substitution. A surrounding pattern operation on the result may cancel it. Hence, for example, if the parameter foo is set to *, ${~foo//\*/*.c} is substituted by the pattern *.c, which may be expanded by filename generation, but ${${~foo}//\*/*.c} substitutes to the string *.c, which will not be further expanded.

So:

t () { ls -d ~/${~1} }
alias t="noglob t"

By the way, test is a POSIX shell builtin (aka [). Don't shadow it.

Upvotes: 4

Related Questions