25

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.

AdminBee
  • 21,637
  • 21
  • 47
  • 71
Vlad GURDIGA
  • 353
  • 1
  • 3
  • 8
  • 4
    What is this character? `ɀ`? – slm Mar 02 '14 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](http://en.wikipedia.org/wiki/%E2%B1%BF) – Gilles 'SO- stop being evil' Mar 02 '14 at 23:32
  • 1
    @Gilles Is that a prompt? – slm Mar 02 '14 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 Mar 03 '14 at 00:51
  • Could you please let us know which version of Bash in which system did you use? Please check my reply: I have not found a version of Bash (in recent distributions) where it does not work as you expected. – pabouk - Ukraine stay strong Sep 22 '14 at 10:52
  • 1
    "GNU bash, version 3.2.53(1)-release (x86_64-apple-darwin13)" shipped with OS X 10.9 has this behavior. – natevw Mar 31 '15 at 21:23
  • @natevw: The `globstar` option is supported in Bash since the version 4.0. Older versions should show an error when you try to manipulate the option. I have extended my reply. – pabouk - Ukraine stay strong Jul 08 '15 at 15:44

3 Answers3

18

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
  • 5
    this is the right answer. The OP forgot to set `shopt -s globstar`. – CS Pei Dec 15 '17 at 03: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 Aug 31 '21 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.

Hauke Laging
  • 88,146
  • 18
  • 125
  • 174
8

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
Alex028502
  • 469
  • 7
  • 12