zsh globs: permission denied

You likely don’t need find if you’re using Zsh. Zsh globs can do most of what find can do through its recursive globbing, extended globs and glob qualifiers. For example, your find ./test-folder -type f -name '*.txt' is just ./test-folder/**/*.txt(D.) D to include hidden files to match find‘s default behaviour. You may not need it, . for -type f.

— Stéphane Chazelas, here on unix.stackexchange

The test-folder contains 4 files: a.txt, b.txt, c.txt, and x.jpg.

When I execute ./test-folder/**/*.txt(D.), it returns

zsh: permission denied: ./test-folder/a.txt

What does permission denied mean here? And why it don’t find b.txt and c.txt?

zsh 5.9 (x86_64-apple-darwin23.0)

Asked By: jsx97


The reason you get "permission denied" is because you tried to run the file ./test-folder/a.txt which does not have execute permission and probably is not executable even if it did. As suggested in comments, you need to put a command in front of this to print or operate on the file instead of execute it.

As to advantages of zsh glob over running find, it can greatly simplify command lines that need to do very simple file searches when combined with other commands. However, it lacks the flexibility of the find command, and does not fix the case where you can’t fit all the matched filenames on the command line.

It doesn’t replace find, its just a shortcut, and it’s not meant to be used stand alone as your example attempts.

If all you wanted was a list of files, it might be a toss up if you use zsh glob or find. But if you combine it with another command, for simple searches zsh glob is almost always shorter.

For example, if you wanted to view every txt file in a small directory tree, this might be useful:

less test-folder/**/*.txt

But if you happened to have a directory that ended in .txt this might make less unhappy, so you could filter that by instead using

less test-folder/**/*.txt(.)

which is certainly shorter than

less $(find test-folder -type f -name '*.txt')

and doesn’t do quite the same thing as

find test-folder -type f -name '*.txt' -exec less {} +

Changing the zsh glob ending from *.txt(.) to *.txt(D.) would allow it to also match the exact filename .txt which would otherwise be skipped.

Answered By: user10489
Categories: Answers Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.