My script takes optional parameters (-i, -w) and a filename in a given directory. How can I tell zsh to complete only regular files (not directories or symlinks) in $HOME/data

This is what I have in my /usr/share/zsh/functions/Completion/Unix/_my-script.

#compdef my-script

_my-script() {
    integer ret=1
    local -a args
    '-i[case insensitive]'
    '-w[match whole words]'

    _arguments $args[@] && ret=0
    return ret


where do I add the _files and how do I tell zsh to only complete regular files in $HOME/data ?

Also, I assume the firs line #compdef my-script is not a comment. How can I add comment to my completion file?

1 Answer 1


The file name is argument 1, so pass 1 to _arguments. Position 1 takes (is) an argument, so the argument to _arguments looks like 1:description:code to do the completion. To specify which files to complete, pass options to _files, some of which are inherited from _path_files: -W to complete inside a given directory, -g to match a specific pattern which can include glob qualifiers to restrict file types. Use _path_files instead of _files because _files always offers directories, whereas with _path_files directories are not offered if -g doesn't let them through.

args=( …
  '1:thing:_path_files -W ~/data -g "*(.)"'

If you want to write a comment, just write a comment the normal way. #compdef … on the first line is a magic comment that tells zsh that this file contains a completion function for my-script. It's equivalent to having compdef _my-script my-script in your init file. It needs to be on the first line.

  • thank you. but it still shows directories in the completions. Can I ignore directories entirely? I am only interested in first level files. Jul 13, 2020 at 8:17
  • @400theCat Ah yes, forgot about that. Use _path_files instead of _files. Jul 13, 2020 at 8:32

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .