Код: Выделить всё
$ tree /tmp/test
/tmp/test
├── dir_a
│ ├── dir a\012file with CR
│ ├── dir a file with spaces
│ └── sub a directory
│ └── with a file in it
├── dir_b
│ ├── dir b\012file with CR
│ └── dir b file with spaces
├── dir_c
│ ├── \012
│ ├── dir c\012file with CR and *
│ └── dir c file with space and *
├── file_1
├── file_2
└── file_3
4 directories, 11 files
Похоже, существуют существенные различия в реализации рекурсивного подстановки между Bash 5.1, zsh 5.8, Python pathlib 5.10, модулем Python glob с включенной рекурсией и Ruby 3.0.< /p>
Это также предполагает, что shopt -s globstar с Bash и cwd является текущим рабочим каталогом и для этого примера установлено значение /tmp/test.
p>
Вот что делает Bash:
- Только файлы и каталоги в cwd. т.е. 3 каталога, 3 файла
Код: Выделить всё
* - Все файлы и каталоги в дереве, корнем которых является cwd, но не cwd — файлы 4 и 11
Код: Выделить всё
** - Только каталоги в дереве, корнем которых является cwd, но не включая cwd – 4 и 0
Код: Выделить всё
**/ - Все каталоги в cwd и все файлы, КРОМЕ файлов в cwd — 4 и 8 файлов, поскольку рекурсия запускается только в подкаталогах
Код: Выделить всё
*/** - То же, что ** – 4 и 11
Код: Выделить всё
**/* - Только каталоги в дереве — 4 и 0 файлов
Код: Выделить всё
**/*/ - Только каталоги ниже второго уровня и файлы ниже первого — 1 и 8.
Код: Выделить всё
*/**/*
Код: Выделить всё
# no shebang - execute with appropriate shell
# BTW - this is how you count the result since ls -1 ** | wc -l is incorrect
# if the file name has \n in it.
cd /tmp/test || exit
[ -n "$BASH_VERSION" ] && shopt -s globstar
[ -n "$ZSH_VERSION" ] && setopt GLOBSTARSHORT # see table
dc=0; fc=0
for f in **; do # the glob there is the only thing being changed
[ -d "$f" ] && (( dc++ ))
[ -f "$f" ] && (( fc++ ))
printf "%d, %d \"%s\"\n" $dc $fc "$f"
done
printf "%d directories, %d files" $dc $fc
glob
Bash
zsh
zsh GLOBSTARSHORTpathlib
python glob
ruby
Код: Выделить всё
*3,3
3,3
3,3
3,3
3,3
Код: Выделить всё
**3,3
4,11
5,0‡
5,11‡
3,3
Код: Выделить всё
**/4,0
4,0
5,0‡
5,0‡
5,0‡
< /tr>
Код: Выделить всё
*/**1,7
1,8
4,0
4,8
1,7
Код: Выделить всё
**/*4,11
4,11
4,12†
4,11
4,11
Код: Выделить всё
**/*/4,0
4,0
4,12†
4,0
4,0
Код: Выделить всё
*/**/*1,8
1,8
1,9†
1,8
1,8
‡ Число каталогов, равное 5, означает, что также возвращается CWD.
† Pathlib Python сохраняет скрытые файлы; остальные нет.
Сценарий Python:
Код: Выделить всё
from pathlib import Path
import glob
tg="**/*" # change this glob for testing
fc=dc=0
for fn in Path("/tmp/test").glob(tg):
print(fn)
if fn.is_file():
fc=fc+1
elif fn.is_dir():
dc=dc+1
print(f"pathlib {dc} directories, {fc} files\n\n")
fc=dc=0
for sfn in glob.glob(f"/tmp/test/{tg}", recursive=True):
print(sfn)
if Path(sfn).is_file():
fc=fc+1
elif Path(sfn).is_dir():
dc=dc+1
print(f"glob.glob {dc} directories, {fc} files")
Код: Выделить всё
dc=fc=0
Dir.glob("/tmp/test/**/").
each{ |f| p f; File.directory?(f) ? dc=dc+1 : (fc=fc+1 if File.file?(f)) }
puts "#{dc} directories, #{fc} files"
Документация:
- Bash:
< em>два соседних символа '*, используемые как один шаблон, будут соответствовать всем файлам и нолю или более каталогам и подкаталогам. - zsh: a) setopt GLOBSTARSHORT устанавливает **.c эквивалентным **/*.c и b) '**/' эквивалентен '(*/)#'; обратите внимание, что это соответствует файлам как в текущем каталоге, так и в подкаталогах.
- pathlib: ** что означает «этот каталог и все подкаталоги рекурсивно»
- python glob: если рекурсивно установлено значение true, шаблон ** будет соответствовать любым файлам и нулю или более каталогов, подкаталогов и символических ссылок на каталоги. Если за шаблоном следует os.sep или os.altsep, файлы не будут совпадать.
- ruby: ** Сопоставляет каталоги рекурсивно, если за ними следует /. Если этот сегмент пути содержит какие-либо другие символы, он аналогичен обычному *.
- Правильны ли мои предположения о том, что должен делать каждый шарик?
- Почему Bash — единственный рекурсивный инструмент с **? (если вы добавите setopt GLOBSTARSHORT в zsh, результат будет аналогичен **
- Is разумно сказать себе, что **/* работает для всех
Подробнее здесь: https://stackoverflow.com/questions/706 ... n-and-ruby