Bash Directory Glob Matching

If I have a file structure like the below, how can I list all files under directories with xyz using globs? When I run ls **/xyz/** on my Mac, I only get locales/xyz/file1.js and locales/xyz/file2.js

But I want: locales/xyz/file1.js, locales/xyz/file2.js, server/routes/private/xyz/file3.js, and src/components/xyz/file4.js

locales/abc/
locales/xyz/
server/routes/private/abc/
server/routes/private/xyz/
src/components/abc/
src/components/xyz/

In short, it depends on your shell and its configuration.

For bash 5.1, you want shopt -s globstar per:

for zsh, it just works:

~ % cd $(mktemp -d)
tmp.MdY5e95E % mkdir -p locales/abc/ locales/xyz/ server/routes/private/abc/ server/routes/private/xyz/ src/components/abc/ src/components/xyz/
tmp.MdY5e95E % find .
.
./locales
./locales/abc
./locales/xyz
./server
./server/routes
./server/routes/private
./server/routes/private/abc
./server/routes/private/xyz
./src
./src/components
./src/components/abc
./src/components/xyz
% for a in $(find .); do mv $(mktemp) $a;
done
% find .
.
./tmp.6bSbqo6W
./locales
./locales/abc
./locales/abc/tmp.ATPOTdgo
./locales/xyz
./locales/xyz/tmp.qCDtHtg4
./locales/tmp.YgFrl1yn
./server
./server/tmp.Pv2KtZXw
./server/routes
./server/routes/private
./server/routes/private/abc
./server/routes/private/abc/tmp.fR9GCEY0
./server/routes/private/tmp.Ob13L7On
./server/routes/private/xyz
./server/routes/private/xyz/tmp.1s4nsA5h
./server/routes/tmp.AScykWo9
./src
./src/tmp.QQkmHT2R
./src/components
./src/components/abc
./src/components/abc/tmp.FSBIQs84
./src/components/xyz
./src/components/xyz/tmp.eFmcB0MF
./src/components/tmp.lZIxnAW0
% ls **/xyz/**
locales/xyz/tmp.qCDtHtg4		src/components/xyz/tmp.eFmcB0MF
server/routes/private/xyz/tmp.1s4nsA5h
% bash
bash-5.1$ ls **/xyz/**
locales/xyz/tmp.qCDtHtg4
bash-5.1$ shopt -s globstar
bash-5.1$ echo **/xyz/**
locales/xyz locales/xyz/tmp.qCDtHtg4 server/routes/private/xyz server/routes/private/xyz/tmp.1s4nsA5h src/components/xyz src/components/xyz/tmp.eFmcB0MF
1 Like

Thanks. I think it might be a Mac bash thing because when I run shopt -s globstar, I get bash: shopt: globstar: invalid shell option name

My guess is your other bash is 3.2, and afaict, the feature was added in bash 4:
https://mywiki.wooledge.org/glob#globstar_.28since_bash_4.0-alpha.29

Personally, I’d suggest using find(1), but beware that find may be gnu find or bsd find and using them portably requires some amount of care:
https://mywiki.wooledge.org/UsingFind