Когда заключать строки в кавычки в командах оболочки Linux?

я обнаружил некоторое несоответствие с командами bash и хотел получить некоторые пояснения.

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

find . -name *.txt

Не получить ошибку, он должен расширять вывод с помощью подстановочного знака?

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

find . -regex '.*x.txt'

Почему это работает, а не ищет файл с буквальным названием .*.txt

Ура


person 123    schedule 18.07.2018    source источник
comment
Это не по теме, потому что это не о программировании.   -  person Jonathon Reinhart    schedule 18.07.2018
comment
Однако обратите внимание, что если шаблон подстановочного знака оболочки ничего не соответствует, то он передается приложению как есть. Вам нужно тщательно продумать разницу между тем, что расширяется оболочкой, и тем, что обрабатывается приложением. Напишите небольшую утилиту, которая просто выводит свои аргументы, и поэкспериментируйте, вызывая ее с разными вещами.   -  person Jonathon Reinhart    schedule 18.07.2018
comment
Когда необходимо. Как только вы узнаете, что на самом деле делает цитирование, легко понять, когда оно необходимо, а когда нет.   -  person chepner    schedule 18.07.2018
comment
Это может быть связано с программированием. Написание сценариев оболочки — это форма программирования. Однако он очень широк. (Конечно вопрос в заголовке....)   -  person Stephen C    schedule 18.07.2018


Ответы (1)


Оболочка расширяет шаблоны без кавычек (где шаблон — это слово, содержащее метасимвол шаблона, такой как *) перед вызовом команды, содержащейся в командной строке. В этом случае find . -name *.txt расширяется, возможно, до find . -name a.txt b.txt c.txt, и в этом случае только a.txt является аргументом основного -name команды find. Чтобы предотвратить это расширение, вы заключаете *.txt в кавычки, потому что вы хотите, чтобы эта литеральная строка была аргументом.

find . -name '*.txt'

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

bash позволяет вам быть несколько ленивым, потому что, если *.txt на самом деле ничему не соответствует, то по умолчанию оно рассматривается как литеральная строка. Существуют параметры оболочки, которые изменяют это поведение: nullglob приводит к тому, что несопоставленный шаблон просто исчезает, как будто его никогда не существовало, а failglob вместо этого вызывает ошибку оболочки. Однако лучше быть явным: если вы не хотите, чтобы строка подвергалась расширению имени пути, заключите ее в кавычки, чтобы убедиться, что ее нельзя расширить.

person chepner    schedule 18.07.2018
comment
Я просто читаю одиночное голосование против двойной кавычки в моей предыдущей ссылке. В своем примере № 11 он говорит, что глобусирование не работает в строках в кавычках любого типа. Тогда почему это работает буквально в каждом написанном человеком сценарии, таком как '*.txt'? - person 123; 18.07.2018
comment
@123: подстановка не работает в строках в кавычках правильно, в оболочке. Но find не является частью оболочки, это внешняя программа со своей собственной системой подстановки. При передаче find параметр '*.txt' должен быть заключен в кавычки, поскольку он анализируется оболочкой до вызова внешней find программы. Если бы он не был защищен, оболочка вскочила бы и расширила его еще до того, как find был запущен. - person cdarke; 18.07.2018
comment
@cdarke Интересно, как мне отличить внутреннюю программу от внешней. Являются ли внутренние программы просто сценариями, которые мы делаем сами, а внешние программы - это те, которые предварительно скомпилированы в ОС? - person 123; 18.07.2018
comment
Нет, внутренние команды — это те, которые реализуются самой оболочкой. Некоторые из них не могут быть реализованы как внешние команды (например, cd, которая изменяет состояние оболочки), в то время как другие могут быть реализованы как таковые (например, test, которая существует как обе; внутренняя версия более эффективна, поскольку не требует нового процесс, который нужно разветвить). Документация оболочки (например, справочная страница) содержит список поддерживаемых встроенных внутренних команд. - person chepner; 18.07.2018
comment
Как говорит @chepner, простой способ узнать, является ли команда встроенной или внешней, - это использовать команду type. Попробуйте type cd, type echo, type ls, type find, type [[. Если вы получаете hashed, это означает, что это внешняя программа, в которой кэшируется путь. - person cdarke; 18.07.2018