26

I have this directory structure:

~/tmp/globstar ɀ  find dir -type f
dir/file.ext
dir/subdir1/file.ext
dir/subdir2/file.ext

and, with the globstar option enabled in Bash, I can say:

~/tmp/globstar ɀ  ls -1 dir/**/*.ext
dir/subdir1/file.ext
dir/subdir2/file.ext

My question is: why is dir/file.ext excluded from this list?

Bash manual says this about globstar:

If set, the pattern ‘**’ used in a filename expansion context will match all files and zero or more directories and subdirectories. If the pattern is followed by a ‘/’, only directories and subdirectories match.

zero” in this paragraph let me with the impression that dir/file.ext should have been included; unless I’m hopefully missing something.

7
  • 5
    What is this character? ɀ?
    – slm
    Commented Mar 2, 2014 at 23:17
  • 2
    What version of bash, on what platform? I can't reproduce this with bash 4.2.37 on Debian wheezy or bash 4.1.5 on Debian squeeze. @slm unicode ɀ or Wikipedia Commented Mar 2, 2014 at 23:32
  • 2
    @Gilles Is that a prompt?
    – slm
    Commented Mar 2, 2014 at 23:41
  • 7
    slm, Yes! ɀ is just a character used here to distinguish prompt. Some users prefer the character £ or instead of $ :). Originally, ɀ a 'z' character created for a special African language notation :-)
    – Slyx
    Commented Mar 3, 2014 at 0:51
  • 1
    "GNU bash, version 3.2.53(1)-release (x86_64-apple-darwin13)" shipped with OS X 10.9 has this behavior.
    – natevw
    Commented Mar 31, 2015 at 21:23

3 Answers 3

19

This works as you expected in these versions of Bash as supplied with the listed distributions:

  • 4.1.2(1) — CentOS 6.5
  • 4.1.5(1) — Debian 6.0.10
  • 4.1.10(4) — Cygwin 1.7.31
  • 4.2.46(1) — CentOS 7.1
  • 4.3.11(1) — Ubuntu 14.04.1
  • 4.3.30(1) — Debian 8.1

In fact the versions listed above are all that I tested. In other words I did not find a version 4 of Bash where it does not work. The option globstar was added in Bash 4.0 see CHANGES. In older versions the command shopt -s globstar should return an error.

Tests

1. dir/**/*.ext matches dir/file.ext:

~/tests$ ls -1 dir/**/*.ext
dir/file.ext
dir/subdir1/file.ext
dir/subdir2/file.ext

2. **/*.ext matches file.ext:

~/tests$ cd dir
~/tests/dir$ ls -1 **/*.ext
file.ext
subdir1/file.ext
subdir2/file.ext

Preparing the environment for reproducing the tests above:

mkdir -p dir/subdir{1,2}
touch dir/{,subdir{1,2}/}file.ext
shopt -s globstar
2
  • 6
    this is the right answer. The OP forgot to set shopt -s globstar.
    – CS Pei
    Commented Dec 15, 2017 at 3:14
  • Yes, globstar is not set. This answer is right but imho it is not enough. The OP's test is very limited, since it does not test subdir1/subsubdir. So, as Alex028502 said: "With globstar off, ** ends up behaving just like *"
    – duthen
    Commented Aug 31, 2021 at 14:35
9

I guess that refers to the subdirectory level only. ** without / matches

  1. all files and directories

  2. zero or more subdirectories

But it does not completely disappear. **/ means that no files in the highest-level directory which ** applies to are matched.

You need dir/*.ext dir/**/*.ext.

1
  • Yeah, that’s exactly my fallback, it just doesn’t look pretty. ;-) Commented Mar 3, 2014 at 11:56
9

I looks to me like you have/had globstar turned off. It can be turned on on like this:

shopt -s globstar

Not only will it not match zero subdirectories, but it won't match two subdirectories either:

$ find dir -type f #the same as yours except with a directory inside one of the subdirectories
dir/file.ext
dir/subdir1/file.ext
dir/subdir1/subsubdir/file.ext
dir/subdir2/file.ext
$ shopt -u globstar #turn globstar off
$ #will only show files in subdirectories
$ #will not show files in dir or in subsubdir
$ echo dir/**/*.ext
dir/subdir1/file.ext dir/subdir2/file.ext
$ shopt -s globstar #turn globstar on
$ #will show all four files
$ echo dir/**/*.ext
dir/file.ext dir/subdir1/file.ext dir/subdir1/subsubdir/file.ext dir/subdir2/file.ext

With globstar off, ** ends up behaving just like *, so dir/**/*.ext gets the same result as dir/*/*.ext

$ echo dir/*/*.ext
dir/subdir1/file.ext dir/subdir2/file.ext

which sometimes tricks me into thinking globstar is on

check your current globstar setting like this:

shopt | grep globstar
1
  • 4
    You can check a shell option setting directly, as in shopt globstar. Commented Sep 4, 2018 at 13:38

You must log in to answer this question.

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