bash globstar dopasowanie

18

Mam tę strukturę katalogów:

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

a przy globstarwłączonej opcji w Bash mogę powiedzieć:

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

Moje pytanie brzmi: dlaczego jest dir/file.extwykluczony z tej listy?

Podręcznik Bash mówi o globstar:

Jeśli jest ustawiony, wzorzec „**” użyty w kontekście rozszerzenia nazwy pliku będzie pasował do wszystkich plików i zero lub więcej katalogów i podkatalogów. Jeśli po wzorcu występuje znak „/”, tylko katalogi i podkatalogi są zgodne.

Zero ” w tym akapicie pozwala mi odnieść wrażenie, że dir/file.extnależało go uwzględnić; chyba że mam nadzieję, że coś mi umknie.

Vlad GURDIGA
źródło
2
Co to za postać? ɀ?
slm
2
Jaka wersja bash na jakiej platformie? Nie mogę tego odtworzyć w bash 4.2.37 na wheezy Debiana lub bash 4.1.5 na squeeze Debiana. @slm unicode ɀlub Wikipedia
Gilles 'SO- przestań być zły'
1
@Gilles Czy to monit?
slm
5
slm, tak! ɀto po prostu znak użyty tutaj do rozróżnienia monitu. Niektórzy użytkownicy wolą postać £lub zamiast $:). Pierwotnie ɀznak „z” stworzony dla specjalnej notacji w języku afrykańskim :-)
Slyx
1
„GNU bash, wersja 3.2.53 (1) -release (x86_64-apple-darwin13)” dostarczane z systemem OS X 10.9 ma takie zachowanie.
natevw

Odpowiedzi:

8

Myślę, że odnosi się to tylko do poziomu podkatalogu. **bez /zapałek

  1. wszystkie pliki i katalogi

  2. zero lub więcej podkatalogów

Ale to nie znika całkowicie. **/oznacza, że ​​żadne pliki w katalogu najwyższego poziomu, które **dotyczą, nie są dopasowane.

Trzeba dir/*.ext dir/**/*.ext.

Hauke ​​Laging
źródło
Tak, to dokładnie moja awaria, po prostu nie wygląda ładnie. ;-)
Vlad GURDIGA
10

Działa to zgodnie z oczekiwaniami w tych wersjach Bash dostarczanych z wymienionymi dystrybucjami:

  • 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

W rzeczywistości wymienione powyżej wersje są wszystkim, co przetestowałem. Innymi słowy, nie znalazłem wersji 4 Bash, w której nie działa. Opcja globstarzostała dodana w Bash 4.0 patrz ZMIANY . W starszych wersjach polecenie shopt -s globstarpowinno zwrócić błąd.

Testy

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

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

2. **/*.ext mecze file.ext:

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

Przygotowanie środowiska do odtworzenia powyższych testów:

mkdir -p dir/subdir{1,2}
touch dir/{,subdir{1,2}/}file.ext
shopt -s globstar
pabouk
źródło
2
to jest poprawna odpowiedź. OP zapomniał ustawić shopt -s globstar.
CS Pei,
5

Wygląda mi na ciebie, jakbyś wyłączył globstar. Można go włączyć w następujący sposób:

shopt -s globstar

Nie tylko nie będzie pasował do zerowych podkatalogów, ale także nie będzie pasował do dwóch podkatalogów:

$ 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

Przy wyłączonej globstar ** kończy się tak jak *, więc dir/**/*.extotrzymuje ten sam wynik codir/*/*.ext

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

co czasem podpowiada mi, że globstar jest włączony

sprawdź swoje obecne ustawienie globstar w następujący sposób:

shopt | grep globstar
Alex028502
źródło
1
Możesz sprawdzić ustawienie opcji powłoki bezpośrednio, jak w shopt globstar.
Benjamin W.