Iterating over inline array in zsh

I'm trying to figure out how to do a command to multiple items. For example:

mycommmand fileA; mycommand fileB; mycommand fileC;

I can do it like this:

files=(fileA fileB fileC)
for fl in $files; mycommand $fl

When I try to inline this it fails:

$for fl in (fileA fileB fileC); echo $fl
zsh: invalid mode specification

Is this possible in zsh? I scanned through the manual on arrays but it didn't mention how to do this.

1

2 Answers

$for fl in (fileA fileB fileC); echo $fl

Here, ( is parsed as the beginning of a Glob Qualifier, like in ls *(a+2).

The qualifier f stands for files with access rights matching spec, that's why you get the error invalid mode specification, because ileA is not a valid access right spec.

If you try e.g. $for fl in (anotherfileA fileB fileC); echo $fl you get zsh: number expected, because the a qualifier is to select by access time. And so on...

So, how to do it right? -- In zsh there are two possible syntaxes for for loops:#

  • Number one is described in the man page:

    for name ... [ in word ... ] term do list done

    So, as @SadBunny already pointed out, the correct syntax of your example is

    for fl in fileA fileB fileC; echo $fl
  • Number 2 is for the lazy people like me (count the key strokes ;) ), documented in the ALTERNATE FORMS FOR COMPLEX COMMANDS section of man zshmisc:

    for name (word ...) { cmd1; cmd2; }

    which can be simplified for only one command in the loop body by omitting the curly brakets:

    for fl (fileA fileB fileC) echo $fl

    This form has IMHO two main advantages:

    • easyier to remember (exactly one pair of round brackets, no or one pair of curly brackets)
    • works as for fl (fileA fileB fileC) mycommand $fl as well as for fl ($files) mycommand $fl -- same syntax for literal values or variables.

# Not counting the arithmetic for loops in the form for (( [expr1] ; [expr2] ; [expr3] )) do list done

3

Sure it's possible. Remove the brackets:

monsterkill-ub-dt% for fl in (xfile yfile); cat ${fl}
zsh: invalid mode specification
monsterkill-ub-dt% for fl in xfile yfile; cat ${fl}
x
y

This also works:

monsterkill-ub-dt% for fl in *; cat ${fl}
x
y

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like