Результат ls *, ls ** и ls ***

Я знаю, используя команду ls перечислит все каталоги. Но что делает команда ls * ? Я использовал его, и он просто перечисляет каталоги. Звезда перед ls означает, насколько глубоко она может перечислить каталоги?

7 Solutions collect form web for “Результат ls *, ls ** и ls ***”

ls перечисляет файлы и содержимое каталогов, которые передаются в качестве аргументов, и если аргумент не указан, он перечисляет текущий каталог. Он также может быть передан несколько вариантов, влияющих на его поведение (подробности см. В man ls ).

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

Однако, если ls * – командная строка оболочки , то оболочка будет расширять это * в соответствии с правилом оболочки подкачки (также называемым расширением имен файлов или расширением имен файлов ).

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

Например, если текущий каталог содержит файлы . , .. , .foo , -l и foo bar , * будет расширяться оболочкой до двух аргументов, чтобы перейти к ls : -l и foo bar , так что это будет, как если бы вы набрали:

 ls -l "foo bar" 

или

 'ls' "-l" foo\ bar 

Какие три способа выполнить точно такую ​​же команду. Во всех трех случаях команда ls (которая, вероятно, будет выполнена из /bin/ls из поиска каталогов, упомянутых в $PATH ), будет передана этими тремя аргументами: «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 ).

yash добавлен ** в версии 2.0 в 2008 году, включен с опцией extended-glob . Его реализация ближе к zsh в том, что ** не является особенным. В версии 2.15 (2009) он добавил *** как в zsh и два из его собственных расширений:. .** и .*** для включения скрытых дисков при рекурсии (в zsh , D glob-определитель (как в **/*(D) ) рассмотрит скрытые файлы и каталоги, но если вы хотите только пересечь скрытые директории, но не расширять скрытые файлы, вам нужно ((*|.*)/)#* Или **/[^.]*(D) ).

Оболочка рыбы также поддерживает ** . Как и предыдущая версия bash , она следует символическим ссылкам при смене дерева каталогов. Однако в этой оболочке **/* не совпадает с ** . ** является расширением * которое может охватывать несколько каталогов. В fish **/*.c будет соответствовать a/b/cc но не ac , тогда a**.c будет соответствовать ac и ab/c/dc а zsh **/.* Например, должен быть записан .* **/.* . Там *** понимается как ** а затем * так же, как ** .

tcsh также добавила опцию globstar в V6.17.01 (май 2010 г.) и поддерживает как ** и *** à la zsh .

Таким образом, в tcsh , bash и ksh93 (когда соответствующая опция включена ( globstar )) или fish , ** расширяет все файлы и каталоги под текущей, а *** – то же, что и для fish , символическая ссылка пересечение ** для tcsh с globstar и то же, что и * в bash и ksh93 (хотя не исключено, что в будущих версиях этих оболочек также будут пересекаться символические ссылки).

Вы заметили необходимость убедиться, что ни один из расширений не интерпретируется как параметры. Для этого вы бы сделали:

 ls -- * 

Или:

 ls ./* 

Есть несколько команд (это не важно для ls ), где второе предпочтительнее, так как даже с -- некоторые имена файлов могут быть обработаны специально. Это касается - для большинства текстовых утилит, cd и pushd и имен файлов, которые содержат символ = для awk например. Превращение ./ всем аргументам устраняет их особое значение (по крайней мере, для упомянутых выше случаев).

Следует также отметить, что большинство оболочек имеют множество параметров, которые влияют на поведение подстановки (например, игнорируются ли точечные файлы или нет, порядок сортировки, что делать, если нет совпадения …), см. Также параметр $FIGNORE в ksh

Кроме того, в каждой оболочке, но csh , tcsh , fish и zsh , если шаблон globbing не соответствует ни одному файлу, шаблон передается как нерасширенный аргумент, который вызывает путаницу и, возможно, ошибки. Например, если в текущем каталоге нет не скрытого файла

 ls * 

На самом деле вызовет ls с двумя аргументами ls и * . И поскольку файлов нет вообще, поэтому никто не вызывает * , вы увидите сообщение об ошибке от ls (а не оболочки), например: ls: cannot access *: No such file or directory , который, как известно, заставляет людей думать что это было фактически расширением глобусов.

Проблема еще хуже в таких случаях, как:

 rm -- *.[ab] 

Если в текущем каталоге *.b файла *.b или *.b , вы можете в конечном итоге удалить файл с именем *.[ab] по ошибке ( csh , tcsh и zsh будут сообщать об ошибке совпадения и не будут вызывать rmfish не поддерживает подстановочные знаки [...] )).

Если вы хотите передать литерал * в ls , вы должны процитировать этот символ * каким-то образом, как в ls \* или ls '*' или ls "*" . В POSIX-подобных оболочках можно полностью отключить set -o noglob с помощью set -o noglob или set -f (последнее не работает в zsh если только в эмуляции sh / ksh ).


¹ Хотя (*/)# всегда поддерживалась, она была сначала короткой, как ..../ в zsh-2.0 (и потенциально раньше), затем ****/ в 2.1, прежде чем получить свою окончательную форму **/ в 2.2 (начало 1992 года)

Команда ls умолчанию ls . : Список всех записей в текущем каталоге .

Команда ls * означает «запустить ls при расширении шаблона * shell»,

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

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

* – это подстановочный знак, который соответствует 0 или более символам. Некоторые современные оболочки возвращаются в подкаталоги при просмотре ** шаблона.

В некоторых оболочках, в том числе bash 4.x с globstar опцией globstar , ** будет выполнять рекурсивный глобус, нисходящие сопоставленные каталоги. Дополнительные звездочки не изменяют эту операцию.

Вы можете демистифицировать весь процесс, сначала набрав 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 каталогов для каждого из пользователей.

Если вы хотите «глубоко погрузиться», используйте опцию ls -R (рекурсивный) или используйте find, например:

 find . -ls 

«find» будет погружаться в нижнюю часть дерева каталогов (как и «ls -R») и имеет еще много параметров, таких как списки каталогов (-type d), только файлы (-type f) или отображение файлов, имеющих другие характеристики (нет пользователя в / etc / passwd, конкретные разрешения и многое другое). «find» также несколько более безопасен в сценариях (из-за непоследовательных правил глобирования между оболочками, а также специальных экранов для файлов с тире и т. д.).

shell подстановочные подстановки не будут работать только с звездочкой «*» на dotfiles. Чтобы указать только dotfiles, используйте:

ls .??*

Extra * не добавляет уровень глубины. Но если вы попробуете

  ls */*/* 

– вы получите список подпапок подпапок в папках в текущей папке …

Мой главный захват в том, что echo ** / *. Ext обычно будет …

May или May not: укажите файл .ext в текущем каталоге

May или May not: include. *. Ext files

Обычно я бы предпочел, чтобы выражение glob было «** /», и это может привести к пустой строке (без подкаталога). Вот как я конвертирую выражения glob в ввод программы. Конечно, я гарантирую, что есть комментарии, объясняющие это в примерах использования.

  • Сортировка ls по времени, когда слишком много файлов для одного вызова
  • «Ls -b» не работает на macOS
  • Количество файлов в каталоге, начиная с определенного текста
  • Почему ls отображает несуществующий файл?
  • dircolor ошибки, вызванные разрешением ntfs-3g
  • Найти имена каталогов с N вхождениями набора символов
  • Как получить относительные пути с помощью ls?
  • Работа rm / ls с
  • Почему «ls -l» сообщает физический размер для каталога, когда он сообщает логический размер файла?
  • Что означает знак @ в выводе ls на терминале Mac OSX Lion?
  • Linux ls для отображения только даты и размера имени файла
  • Linux и Unix - лучшая ОС в мире.