Search code examples
escapingzsh

zsh escape white space in the "for file in path" syntax


I want to loop through files in "/test/my project/abc/*" using zsh script on Mac OSX.

path="/test/my project/abc/*"
for file in ${path}; do
    something
done

will result in white space not being escaped and error occuring.

I also tried

path="/test/my project/abc/*"
for file in "${path}"; do
    something
done

In most other usage this method of escaping would have worked but in the "for ... in ..." case it instead treat the whole "${path}" as a string array and only list the single string.

I am stuck and any help would be appreciated.


Solution

  • File globbing with a variable expansion is turned off by default in zsh. You have to explicitly request it with ${~...}:

    ls 'sub dir'; print
    
    p="sub dir/*"
    for f in ${~p}; do
        print "in loop: [$f]"
    done
    

    output:

    fl1     fl2     fl3
    
    in loop: [sub dir/fl1]
    in loop: [sub dir/fl2]
    in loop: [sub dir/fl3]
    

    Note that this does not use path as a variable name. path is usually tied to the PATH variable, and is effectively a reserved word in zsh. That may be why you saw different results with your examples; in a default zsh configuration, both the quoted and unquoted forms should simply return the pattern and not the glob results.

    More info:

    • zshexpn - this man page has a description of ${~spec}.
    • GLOB_SUBST is described in zshoptions. This is another way to force globbing with a variable expansion , but it's usually not a good idea to set this option.
    • Some notes about path, PATH, and typeset -T: https://stackoverflow.com/a/18077919/9307265