I would like to list all of the files in a folder called foldername that have the extension test, atest or btest.

My immediate thought was to run ls ./foldername/*.{a,b,}test

This works fine unless there is nothing with the extension atest, in which case I get the error zsh: no matches found: ./foldername/*.atest.

Is there any way I can simply ignore this error and print the files that do exist?

I need this to work in both zsh and Bash.

  • 4
    Redirect standard error to /dev/null?
    – DopeGhoti
    Commented Nov 28, 2017 at 16:48

4 Answers 4



ls -d ./foldername/*.{a,b,}test

{a,b,...} is not a glob operator, that's brace expansion, that's first expanded to:

ls -d ./foldername/*.atest ./foldername/*.btest ./foldername/*.test

And each glob expanded individually, and if any glob doesn't match, the command is cancelled as you'd expect in zsh (or fish; in bash, you need the failglob option to get a similar behaviour).

Here, you'd want to use a single glob that matches all those files, and only cancel the command if that one glob didn't match any file:

ls -d ./foldername/*.(a|b|)test

You don't want to use nullglob, as if none of the globs matched, it would run ls without arguments, so list the current directory. cshnullglob is better in that regard as it removes non-matching globs but still cancels the command if all the globs fail to match.

You wouldn't want to use nonomatch, as that would give you the broken behaviour of bash which would be a shame.

For a glob alternative that works in both zsh and bash, you could use the ksh globs (set -o kshglob in zsh and shopt -s extglob in bash).

Then, you'd do:

ls -d ./foldername/*.@(a|b|)test


ls -d ./foldername/*.?([ab])test

Add the failglob option in bash to avoid the glob being passed literally to ls when it doesn't match.

See Why is nullglob not default? for more information.

  • I'm not sure why it's a requirement of the OP, but is there an extglob that works for this in both bash and zsh? I had to use ?(...) or +(...) for bash.
    – Jeff Schaller
    Commented Nov 28, 2017 at 17:28
  • @JeffSchaller, see edit Commented Nov 28, 2017 at 17:33

It may be best to do this with find:

find ./foldername -maxdepth 1 -name '*.atest' -o -name '*.btest' -o -name '*.test'
  • 1
    perhaps with a -maxdepth 1, to closer emulate the ls behavior
    – Jeff Schaller
    Commented Nov 28, 2017 at 17:29
  • 4
    @JeffSchaller, note that -maxdepth is a GNU extension. Note 3 other differences with globs: find would include hidden files, not sort the list and fail to match file names that contain bytes not forming valid characters (like a $'St\xe9phane.atest' in a UTF-8 locale) Commented Nov 28, 2017 at 17:32

I faced this problem, and first solved it by hacking ls itself. When finished, I realised that all I needed was the trival C program:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int main(int argc, char* argv[]) {
  struct stat statbuf;
  int i;
  for( i=1; i<argc; i++ ) {
    if( stat(argv[i],&statbuf) == 0 ) {

All this does, and all it needs to do, is to run through its command line arguments and echo those strings that correspond to valid files (that is, for which stat() succeeds).

Of course, we can emulate this with equally simple Python, Perl, or even a shell function that runs stat, but writing it in C makes it much quicker to run.

As for hacking ls, I've put a run through on my personal wiki: http://linux.chalisque.net/LsIgnoreMissing


Comment from @DopeGhoti worked for me.

i.e. Redirecting the error to /dev/null using 2> operator like so:

ls ./foldername/*.{a,b,}test 2> /dev/null
  • No, it wouldn't work in zsh where this question is about as you'd only be redirecting ls' stderr, and ls is not even run here in zsh if any of those globs fail. Commented Mar 6, 2022 at 17:20

You must log in to answer this question.

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