Відповіді:
ls
перераховує файли та вміст каталогів, які вони передаються як аргументи, і якщо аргумент не наводиться, він містить список поточного каталогу. Також може бути прийнято ряд варіантів, які впливають на його поведінку (детальніше див. man ls
).
Якщо ls
передається аргумент, який називається *
, він шукатиме файл або каталог, названий *
у поточному каталозі, і перелічує його так само, як і будь-який інший. ls
не відноситься до *
персонажа будь-яким іншим способом, ніж будь-який інший.
Однак , якщо ls *
це оболонка командного рядка, то оболонка буде розширюватися , що в *
відповідно до відповідної оболонкові підстановка (також згадується як Filename Generation або Filename Expansion ) правил.
Хоча різні оболонки підтримують різних глобальних операторів, більшість з них погоджуються на найпростіший *
. *
як візерунок означає будь-яку кількість символів, так *
що glob
розширення відобразиться до списку файлів у поточних каталогах, що відповідають цьому шаблону. Однак є виняток, що провідний символ dot ( .
) у імені файлу має бути явно узгоджений, тому він *
фактично розширюється до списку файлів і каталогів, не починаючи з .
(у лексикографічному порядку).
Наприклад, якщо поточний каталог містить файли , звані .
, ..
, .foo
, -l
і foo bar
, *
буде розширено за рахунок оболонки двох аргументів для передачі ls
: -l
і foo bar
, таким чином , це буде , як якщо б ви ввели:
ls -l "foo bar"
або
'ls' "-l" foo\ bar
Які три способи запустити абсолютно одну команду. У всіх 3 випадках ls
команда (яка, ймовірно, буде виконана з /bin/ls
пошуку каталогів, згаданих у $PATH
), передасть ці 3 аргументи: "ls", "-l" та "foo bar".
Між іншим, в цьому випадку ls
буде розглядатись перший (строго кажучи другий ) варіант.
Зараз, як я вже сказав, різні оболонки мають різних операторів, що займаються глобалізацією. Кілька десятиліть тому, zsh
представив **/
operator¹ , що означає , щоб відповідати будь-якого рівня підкаталогів, скорочення (*/)#
і ***/
що те ж саме , за винятком того , що слід симлінк при спуску каталогів.
Кілька років тому (липень 2003 р. ksh93o+
) ksh93
Вирішили скопіювати таку поведінку, але вирішили зробити її необов'язковою і лише висвітлювали **
справу (не ***
). Крім того, хоча **
сам по собі не був особливим zsh
(просто мав на увазі те саме, що *
і в інших традиційних оболонках, оскільки **
означає, що будь-яка кількість символів, а за ними будь-яка кількість символів), у ksh93 **
означало те саме, що **/*
(тому будь-який файл чи каталог нижче поточного (за винятком прихованих файлів).
bash
скопійовано ksh93
через кілька років (лютий 2009 р., bash 4.0) з тим самим синтаксисом, але прикрою різницею: bash's **
було схоже на zsh
's' ***
, тобто це слідування посилання на повторне повторення в підкаталогах, що, як правило, не те, що ви хочете робити. може мати неприємні побічні ефекти. Частково це було зафіксовано в bash-4.3, оскільки символьні посилання все ще дотримувалися, але рекурсія там припинилася. Це було повністю зафіксовано в 5,0.
yash
Додано **
у версії 2.0 у 2008 році, включено з extended-glob
опцією. Її реалізація ближча до zsh
російської, тому що **
лише вона не є особливою. У версії 2.15 (2009) він додав ***
як у, так zsh
і два власні розширення: .**
і .***
для включення прихованих файлів при повторному повторенні (в zsh
, глобальний D
класифікатор (як у **/*(D)
) буде враховано приховані файли та каталоги, але якщо ви хочете лише перейти приховані dirs, але не розширюйте приховані файли, вам потрібно ((*|.*)/)#*
або **/[^.]*(D)
).
Ракоподібні також підтримує **
. Як і в попередній версії програми bash
, під час спадання дерева каталогів воно слідує за посиланнями. Однак у цій оболонці **/*
не те саме, що **
. **
це більше розширення, *
яке може охоплювати декілька каталогів. В fish
, **/*.c
буде відповідати , a/b/c.c
але не a.c
, в той час як a**.c
буде відповідати a.c
і ab/c/d.c
та zsh
«s **/.*
, наприклад , має бути написано .* **/.*
. Там, ***
розуміється, як **
слідує, *
так само, як **
.
tcsh
також додав globstar
опцію у V6.17.01 (травень 2010 р.) та підтримує обидва **
та ***
а-ля zsh
.
Так tcsh
, bash
і ksh93
(якщо відповідна опція ( globstar
)) або fish
, **
розгортає все файли і каталоги нижче поточного, і ***
така ж , як **
для fish
, символьного посилання , що перетинає **
для tcsh
з globstar
, і так само , як *
в bash
і ksh93
(хоча це не неможливо, що майбутні версії цих оболонок також будуть перетинати символьні посилання).
Вище ви помітили необхідність переконатися, що жодне з розширень не трактується як варіант. Для цього ви зробите:
ls -- *
Або:
ls ./*
Є деякі команди (це не має значення ls
), де друга є кращою, оскільки навіть з --
деякими іменами може бути оброблена спеціально. Це справа -
для більшості текстових утиліт, cd
а pushd
й імена файлів , які містять =
символ для awk
, наприклад. Попередньо ./
до всіх аргументів вилучається їх особливе значення (принаймні, для випадків, зазначених вище).
Слід також зазначити, що більшість оболонок мають ряд варіантів, які впливають на поведінку глобулінгу (наприклад, ігноровані чи не файли крапок, порядок сортування, що робити, якщо немає відповідності ...), див. Також $FIGNORE
параметр уksh
Крім того , в будь-оболонці , але csh
, tcsh
, fish
і zsh
, якщо підстановка шаблон не відповідає будь-якому файлу, шаблон передається в якості аргументу нерозкритого , що викликає плутанину і , можливо , помилку. Наприклад, якщо в поточному каталозі немає прихованого файлу
ls *
Справді зателефонуйте ls
з двома аргументами ls
і *
. А оскільки файлу взагалі немає, так що жоден з них не викликається *
, ви побачите повідомлення про помилку ls (не оболонки) типу:, ls: cannot access *: No such file or directory
яке, як відомо, змусило людей думати, що саме ls
це насправді розширює глобус.
Проблема ще гірша у таких випадках:
rm -- *.[ab]
Якщо немає ніякого , *.a
ні *.b
файл в поточному каталозі, то ви можете в кінцевому підсумку видалити файл з ім'ям *.[ab]
помилково ( csh
, tcsh
і zsh
буде повідомляти не рівня помилку і не назвав би rm
(і fish
не підтримує [...]
символи узагальнення)).
Якщо ви хочете передати буквальне *
значення ls
, ви повинні *
якось цитувати цього символу, як у ls \*
або ls '*'
або ls "*"
. У оболонках, схожих на POSIX, глобус можна взагалі відключити за допомогою set -o noglob
або set -f
(останні не працюють, zsh
якщо не в sh
/ ksh
емуляція).
¹ Хоча (*/)#
його завжди підтримували, спочатку він був короткостроковим, як ..../
у zsh-2.0 (а можливо і раніше), потім ****/
у 2.1, перш ніж набути своєї остаточної форми **/
в 2.2 (на початку 1992 р.)
find -name *
. Особливо зі складнішими шаблонами, якщо в поточному каталозі є одна одна відповідність, люди часто не усвідомлюють, що вони не передають зірочку find
.
*.[ab]
намагаються видалити все, що закінчується .[ab]
. [
не відрізняється рибою.
Команда ls
за замовчуванням ls .
: Список усіх записів у поточному каталозі .
Команда ls *
означає "запустити ls на розширення *
шаблону оболонки"
*
Шаблон обробляється оболонкою, і розширюється до всіх записів в поточному каталозі, за винятком тих , які починаються з .
. Це піде на один рівень глибше.
Інтерпретація подвійних чи потрійних *
моделей залежить від фактично використовуваної оболонки.
*
являє собою підстановку, яка відповідає 0 або більше символів. Деякі сучасні оболонки будуть повторюватися у підкаталоги, коли ви побачите **
викрійку.
*
зробити щось то додати, побачити іншу відповідь , яка пояснювала б globstar. Слід також зрозуміти, що ls не має нічого спільного з зірочками, ніколи взагалі не передається жодна з цих зірочок. Біжіть, echo ls *
щоб побачити, що буде виконуватися під час написання ls *
.
Ви можете демістифікувати весь процес, ввівши echo
замість ls
першого, щоб побачити, на що команда розширюється:
$ echo *
Applications Downloads Documents tmp.html
Тож у цьому випадку ls *
розширюється доls Applications Downloads Documents tmp.html
$ echo **
Applications Downloads Documents tmp.html
$ echo ***
Applications Downloads Documents tmp.html
Тож ніяких змін. Це передбачає, що ви використовуєте bash
як свою оболонку - більшість людей є, а різні оболонки мають різну поведінку. Якщо ви використовуєте ash
або csh
або ksh
або zsh
, ви можете очікувати речі працювати по- іншому. Це сенс мати різні снаряди.
Тож давайте спробуємо щось інше (все ще з bash
), щоб ми отримали уявлення про те, що *
оператор globbing ( ) може зробити для нас. Наприклад, ми можемо фільтрувати за частиною назви:
$ echo D*
Downloads Documents
І що цікаво, косою косою рисою є неявна частина будь-якої назви каталогів. Так */
вийде лише каталоги (і символьні посилання на каталоги):
$ echo */
Applications/ Downloads/ Documents/
І ми можемо виконати деяку фільтрацію на декількох рівнях, поставивши косу рису в середину:
$ echo D*/*/
Documents/Work/ /Documents/unfinished/
Оскільки Downloads
каталог не містить підкаталогів, він не закінчується у висновку. Це дуже корисно для простого вивчення потрібних файлів. Я постійно використовую такі команди:
$ ls -l /home/*/public_html/wp-config.php
У цьому списку перераховані всі wp-config.php
файли, що існують на базовому рівні будь-якого public_html
каталогу користувачів, якщо такі є . А може бути більш повним:
$ find /home/*/public_html/ -name wp-config.php
Це дозволить знайти будь-які wp-config.php
файли в будь-якого користувача public_html
каталогів або будь-який з їх підкаталогів, але він буде працювати більш ефективно , ніж просто find /home/ -name wp-config.php
тому , що він не буде нічого досліджувати , але в public_html
каталогах для кожного з користувачів.
bash
як свою оболонку" ← і що globstar не ввімкнено. shopt -s globstar
і спробуйте ще раз ...
set -x
який почне друкувати команду "фактично", що виконується щоразу (вимикайте set +x
).
У деяких оболонках, включаючи bash 4.x з globstar
увімкненою опцією, **
буде виконуватися рекурсивний глобус, у відповідності зі спадними каталогами. Додаткові зірочки більше не змінюють цю операцію.
ksh93
і zsh
, bash
чи проходить символічна посилання в рекурсії, яка взагалі небажана.
Якщо ви хочете "зануритися вглиб", скористайтеся параметром ls -R (рекурсивний) або використовуйте "find", наприклад:
find . -ls
"find" зануриться вниз до низу дерева каталогів (як і 'ls -R'), і має багато інших варіантів, наприклад, перелічення каталогів (-type d), лише файли (-type f) або показ файлів, що мають інші характеристики (немає користувача в / etc / passwd, конкретні дозволи та ще багато іншого). "find" також дещо безпечніший у сценаріях (через суперечливі правила глобулювання між оболонками, а також спеціальні втечі для файлів з тире та ін.).
Глобулювання шаблону шаблону не працюватиме лише зірочкою "*" на точкових файлах. Для переліку лише точкових файлів використовуйте:
ls .??*
Extra * не додає рівня глибини. Але якщо спробувати
ls */*/*
- ви отримаєте список папок підпапок у папках у поточній папці ...
*
s додадуть рівень глибини.
bash
з опцією globstar, оболонку korn та zsh. І, можливо, інші, я б здогадався. unix.stackexchange.com/a/62665/14831
Моя головна хватка полягає в тому, що відлуння ** / *. Ext, як правило, ...
Травень чи травень: список файлу .ext у поточному каталозі
Може або не: включати файли. *. Ext
Як правило, я вважаю за краще вираз глобуса "** /", який може призвести до нульового рядка (немає підкаталогу). Ось так я перетворюю глобальні вирази у вхід програми. Звичайно, я страхую, що є коментарі, що пояснюють це на прикладах використання.