Почему команды расширяются в Bash до их запуска? - PullRequest
0 голосов
/ 02 мая 2018

Я выполнял команду find . -name *.bak и получал ошибки "Paths must precede expression" ошибки. На этот вопрос ответили, и ответ довольно хороший, но я не понимаю, почему bash расширяет подстановочный знак до запуска команды find? оригинальный пример .

В нем говорится, что find . -name *.bak расширен до find . -name tim.bak example.bak. Может кто-нибудь объяснить, почему он расширен, я не могу понять, почему было бы неплохо иметь эту функцию для глобусов.

Ответы [ 3 ]

0 голосов
/ 02 мая 2018

Это проектное решение, которое было принято очень рано в истории Unix. Подстановочные знаки имени файла должны быть расширены в некоторый момент, но есть выбор относительно того, должен ли это делать интерпретатор команд (он же оболочка), и результат (список совпадающих файлов) передается исполняемому файлу, или интерпретатор команд должен просто передайте то, что он дал исполняемому файлу, и сделайте так, чтобы он сделал расширение. Разные ОС делают это по-разному; Unix делает первое, но VMS (который я использовал до перехода на Unix) делает это вторым способом. Оба имеют свои преимущества и недостатки.

  • Основное преимущество unix way заключается в том, что код расширения с подстановочными символами должен быть написан и использован только в одном месте: в оболочке. Команды просто не должны беспокоиться об этом. Во-вторых, вы можете улучшить / расширить соответствующий синтаксис (например, синтаксис bash для extglob), внеся изменения в one place . В-третьих, вы получаете согласованный синтаксис расширения между всеми различными командами (вместо того, чтобы изучать разные правила для разных команд, например, базовый или расширенный или совместимый с perl беспорядок регулярных выражений).

  • Основным преимуществом пути VMS является то, что исполняемая программа знает, что означают аргументы, и может соответствующим образом изменить / подавить расширение. Например, find будет знать, что не следует расширять символы подстановки в текущем каталоге, grep будет знать, что не будет пытаться расширить шаблон регулярного выражения, как если бы это был подстановочный знак файла, scp может расширить символ подстановки в удаленный компьютер и т. д. Второе преимущество заключается в том, что подстановочные знаки могут использоваться способами, которые система Unix просто не позволяет, потому что программа лучше понимает, как указываются аргументы; например rename *.jpeg *.jpg - это (если я правильно помню) очень хорошая команда VMS, которая делает именно то, что должна выглядеть.

    [Редактировать] Еще одним преимуществом является то, что он исключает риск того, что имена файлов будут приняты за параметры команды. Это может быть серьезной проблемой безопасности с подходом Unix, так как любой, кто может управлять именами файлов, может также иметь возможность управлять командами и сценариями, которые работают с этими файлами. Например, создание файла с именем «-e somecommand» приведет к выполнению rsync -t * foo:src/ на удаленном компьютере somecommand. В этой статье приведены дополнительные примеры.

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

Как вы могли бы сказать из вышесказанного, я в целом считаю, что VMS лучше. Это немного больше работы для программистов, но имеет значительные преимущества в удобстве использования и мощности. Но я уверен, что это мнение меньшинства среди пользователей Unix, и в любом случае потребовалось бы массивное усилие, чтобы когда-либо изменить то, как Unix это делает, так что, пока unix - это Unix, это не изменится. .

0 голосов
/ 02 мая 2018

Один из отцов-основателей UNIX, Деннис Ритчи, дал такое объяснение:

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

Д.М.Ритчи, в Система разделения времени Unix: ретроспектива BSTJ июль-август 1978

0 голосов
/ 02 мая 2018

Очень краткий ответ:

Так работает Bash, он всегда расширяет то, что может, заменяет переменную на их значения, использует переменные окружения (как, например, $PATH), интерпретирует псевдонимы и передает результат (соответствующий Аргументы) к команде " правильной " (извлеченной из $PATH), которую вы вызываете. Расширение аргумента можно рассматривать как одну из многочисленных обязанностей bash.

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

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

find . -name '*.bak'
             ^     ^

Список обязанностей Shell:

http://www.informit.com/articles/article.aspx?p=31480&seqNum=4 http://ptgmedia.pearsoncmg.com/images/chap3_0672324903/elementLinks/03fig08.jpg http://tldp.org/LDP/abs/html/x9644.html

...