Что означают двойные звездочки?

Я пробовал следующую команду, но у меня проблемы с ее интерпретацией:

ls **

но я не уверен, что он выводит и почему это результат.

Ответы

Ответ 1

Кит ответ правильный. Обратитесь туда.

Рассмотрим следующее дерево каталогов:

folderA
├── file1
├── file2
└── folderB
    ├── file3
    └── folderC

ls выведет список всех объектов в текущей папке:

$ ls
file1  file2  folderB

ls * перечислит все объекты в текущей папке и, кроме того, еще один уровень рекурсивно

$ ls *
file1  file2 

folderB:
file3  folderC

Второе * в ls ** не имеет значения в большинстве случаев, так как shell расширяет подстановочный знак и ls получает результаты первого *

Из руководства по bash

Когда опция оболочки globstar включена и используется в контексте расширения имени файла, два соседних, используемых в качестве единого шаблона, будут соответствовать всем файлам и нулю или большему количеству каталогов и подкаталогов.

Ответ 2

Вероятно, он использует специальную функцию некоторых оболочек, которая позволяет ** выполнять рекурсивное совпадение, в отличие от единственного *, которое соответствует только в текущем каталоге.

Подстановочный знак * соответствует любому файлу или каталогу (имя которого не начинается с .) в текущем каталоге.

В зависимости от используемой оболочки и с какими настройками ** может быть эквивалентно *; он может соответствовать нулю или более символам, за которыми следуют ноль или более символов, что совпадает с совпадением нуля или нескольких символов только один раз.

Но с некоторыми оболочками с некоторыми настройками ** является рекурсивной версией *, соответствующей всем файлам и каталогам в текущем каталоге и подкаталогах.

Цитирование bash руководство:

`* '
     Соответствует любой строке, включая пустую строку. Когда      опция оболочки "globstar" включена, а `* 'используется в имени файла      контекст расширения, два смежных `*, используемых как один шаблон, будут      сопоставлять все файлы и ноль или более каталогов и подкаталогов.      Если за ним следует `/', два соседних` `* будут совпадать только      каталогов и подкаталогов.

Это работает, только если опция globstar установлена ​​через:

shopt -s globstar

(он отключен по умолчанию) и только в относительно недавних версиях bash.

Я считаю, что zsh также поддерживает этот синтаксис.

Важно помнить, что подстановочные знаки расширяются оболочкой, а не командой ls. Если вы наберете ls ** или ls *.txt, команда ls никогда не увидит символы *; он видит только расширенный список файлов, точно так же, как если бы вы ввели весь список в командной строке.

Ответ 3

Точное поведение этого конкретного группового символа было хорошо охвачено другими ответами, но информация по общему случаю может быть полезной.

Это поведение не ограничивается ls и называется "globbing", которое представляет собой расширение шаблонов на основе совпадений с существующими именами файлов. Важно отметить, что эти шаблоны не используют синтаксис регулярных выражений.

Оболочка предварительно обрабатывает аргументы перед их отправкой в программу. Обычно существует несколько уровней расширения, некоторые из которых связаны с глобализацией.

Отличным ресурсом для получения дополнительной информации о других символах подстановки, доступных в шаблоне глобуса файла, является man-страница unix. Онлайн-версия для glob может быть найдена здесь.

И наконец, простой пример того, что это может сделать для вас, особенно в сочетании с другими полезностями расширения оболочки, в данном случае теми, которые предоставляются оболочкой bash. Информацию о расширениях, использованных в этом примере, можно найти в Руководстве по Bash для начинающих, которое является моим ресурсом goto, несмотря на заголовок.

ls *{01..04}.{txt,csv} становится ls *01.txt *01.csv *02.txt *02.csv *03.txt *03.csv *04.txt *04.csv

Который мог бы вывести что-то вроде этого:

input_01.txt input_02.txt input_03.txt input_04.txt output_01.csv output_02.csv output_03.csv output_04.csv

Пока пропускаем эти:

input_05.txt input_06.txt input_07.txt input_08.txt input_09.txt input_10.txt output_05.csv output_06.csv output_07.csv output_08.csv output_09.csv output_10.csv

Тривиальный пример, но если вы знаете, что это поведение не относится только к ls, вы можете представить себе утилиту в сочетании с mv, cp, rsync и т.д.

Ответ 4

Подобно команде DOS dir, функция команды ls - это список файлов и каталогов. Когда предмет, который будет указан, является файлом, команда просто перечисляет файл, не имеет большого значения. Когда предмет, который будет указан, является папкой, команда перечисляет содержимое папки. Кроме того, если вы просто команда ls без аргументов, то по умолчанию нужно указать рабочий каталог или текущую папку. (Также текущее имя папки всегда ., поэтому голая команда ls эквивалентна ls ..)

Пример. В вашей текущей папке находится файл с именем file_001, папка с именем folder_002, а в папке у вас есть файлы с именем picture_003 и picture_004. Когда вы наберете ls, вы увидите file_001 folder_002, а при вводе ls folder_002 вы увидите picture_003 picture_004.

В Unix подстановочная обработка выполняется оболочкой. Когда вы вводите ls **, ваша оболочка обрабатывает **, прежде чем она запускает команду ls, она заменяет ** именами всех файлов/папок, которые совпадают. (Подстановочный знак * соответствует любому файлу или папке. Использование ** соответствует любому файлу или папке, чье имя начинается с чего-либо и заканчивается чем-либо, поэтому оно функционально эквивалентно просто *.)

В этом случае, когда команда ls запускается, аргументы командной строки представляют собой список всех файлов и папок в текущей папке, точно так же, как вы сами набрали их. Итак, в нашем примере теперь вы выполняете команду ls file_001 folder_002. Когда команда ls обрабатывает свою командную строку, первый элемент является файлом, поэтому он просто перечисляет файл, а второй элемент - это папка, поэтому он перечисляет содержимое папки. Кроме того, поскольку команда перечисляет несколько объектов, она печатает ярлык с именем папки, поэтому вы можете различать содержимое папки в выходном листинге из всего, что еще содержится в списке. В результате вывод команды ls ** будет выглядеть следующим образом:

file_001

folder_002:
picture_003   picture_004`

Мне любопытно. В каком руководстве, книге или документе вы предложили команду ls **?