Чому існує a / bin / echo і чому я хочу його використовувати?


52

Я помітив, що в /bin/echoмоїй системі Ubuntu MATE 17.04 є двійковий виконуваний файл .

Я подумав, що це дивно, бо

$ type echo
echo is a shell builtin

Тестовий тест говорить про те, що /bin/echoробить те саме, що і Bash вбудований echo:

$ /bin/echo foo
foo
$ /bin/echo $USER
zanna

Отже, чому існує інша версія echoокремої програми Bash, і чому або коли я хочу її використовувати?



2
@ bodhi.zazen Це дуже корисно, навіть якщо це не те саме, оскільки воно стосується зворотного цього питання. Це запитання задає, чому echoвін надається як вбудована оболонка, в той час як це запитує, чому він надається як зовнішня команда.
Eliah Kagan

3
Одна з причин - не всі використовують баш. Я б здогадався, що / bin / echo передує bash, і розробники вважають корисним / ефективним включити його як вбудований замість використання виконуваного файлу.
jamesqf

Відповіді:


87

Якщо ви відкриєте bashпідказку і введіть echoкоманду, яка використовує вбудовану оболонку, а не запуску /bin/echo. Причини, для яких все ще важливо /bin/echoіснувати:

  1. Ви не завжди використовуєте оболонку. За різних обставин ви запускаєте виконуваний файл безпосередньо, а не через оболонку.
  2. Принаймні теоретично, деякі снаряди не мають echoвбудованої форми. Насправді цього не потрібно.

Для того, щоб розширити свою присутність на # 1, припустимо , що ви хочете , щоб перемістити всі звичайні файли , чиї імена стали з в abcбудь-якій точці srcдо dest. Існує кілька способів зробити це, але один з них:

find src -name 'abc*' -type f -exec mv -nv {} dest/ \;

Але припустимо, а не просто виконувати це, ви хочете побачити кожну команду, яка буде виконуватися першою. Ну, тоді ви можете додати echoкоманду, як і в інших контекстах:

find src -name 'abc*' -type f -exec echo mv -nv {} dest/ \;

Але findне використовує оболонку. Це працює /bin/echo.

Крім того , findз -execабо-execdir , то /bin/echoвиконуваний файл буде називатися іншими програмами , які самі керують програми , але не через оболонку. Це відбувається з xargsкомандою (яка пов'язана з find), а також в ряді інших контекстах, наприклад, в Exec=рядку в вигляді .desktopфайлу . Інший приклад - під час запуску sudo echo, який може бути корисним для тестування, якщо sudoвін працює.

Так само деякі снаряди мають printfвбудований, але /usr/bin/printfтакож існує.

Менш поширена причина, яку ви можете навмисно використовувати, /bin/echo- це якщо ви покладалися на відмінності між нею та echoкомандою, наданою вашою оболонкою. man echoдокументи /bin/echo; help echoв bash документах bashвбудований. echoне дуже портативний, тому що різні реалізації - як в операційних системах, так і в оболонках однієї операційної системи - підтримують різні варіанти (наприклад, -e) і відрізняються поводженням з накидами . Звичайно, краще уникати покладатися на такі деталі, а використовувати printfзамість цього, який набагато портативніший .

В bash, ви можете зробити typeзумовлені шоу , /bin/echoа також - якщо /binу вашій , $PATHяк це завжди повинно бути - по передавши їй -aпрапор :

$ type -a echo
echo is a shell builtin
echo is /bin/echo

21
А також тому, що специфікація POSIX говорить, що вона повинна бути такою.
glenn jackman

4
@glennjackman Я сподівався, що хтось опублікує відповідь про це насправді, і я сподіваюся, що ви вирішите це зробити! Однак є деякі тонкощі, оскільки ні Debian, Ubuntu, ні GNU Coreutils (ні проект GNU в цілому) намагаються відповідати POSIX у всьому . Наприклад, POSIX наполягає на cdіснуванні виконуваного файлу (який під час запуску змінює каталог і закриває, залишаючи абонента там, де вони були раніше), а деякі ОС мають його. Це може бути корисним для цитування 4.1 у стандартах GNU .
Елія Каган

@EliahKagan: Incidentaly / usr / bin / cd використовує команду: / usr / bin / cd, запускаючи цю команду в цьому каталозі. Якщо зміна каталогу не вдається, команда не запускається.
Джошуа

4
@Joshua краще використання - cdце просто тест на можливість доступу до заданої директорії: якщо це /usr/bin/cd some/dirвдалося, за один кадр ви перевірили: а) що some/dirіснує, б) що це каталог або посилання на один, і в) існують необхідні дозволи для доступу до цього каталогу; все без зміни власної держави.
muru

1
@CarlWitthoft, див. Чому printf кращий за відлуння? Крім того, це /bin/echoне так \bin\echo, якщо ви не використовуєте Windows. ;)
Wildcard

31

Елія зробив чудову роботу, щоб відповісти на це, але я хочу прокоментувати echoчастину "чому існує інша версія окремої програми Bash". Це неправильне питання.

Правильне питання: чому це вбудований в першу чергу , коли він міг бути (і є) ідеально чудовою зовнішньою командою?

Для простоти погляньте на вбудовані тире, потворний 38 (баш має 61, для порівняння, йде за результатами compgen -b):

.               continue        getopts         readonly        type
:               echo            hash            return          ulimit
[               eval            jobs            set             umask
alias           exec            kill            shift           unalias
bg              exit            local           test            unset
break           export          printf          times           wait
cd              false           pwd             trap
command         fg              read            true

Скільки з них потрібно для побудови? [, echo, false, printf, pwd, test, І trueНЕ потрібно бути вбудованими функціями : Вони все , що тільки може зробити вбудований не робити (афект або отримати стан оболонки, недоступна для зовнішніх команд). printfПринаймні, Баш використовує перевагу вбудованості: printf -v varекономить вихідну змінну var. timeв bash також є особливим: будучи ключовим словом, ви можете розміщувати довільні списки команд у bash (тире не має timeеквівалента). pwdтакож не повинно бути вбудованим - будь-яка зовнішня команда буде успадковувати поточну робочу директорію (і це також зовнішня команда ).:є винятком - вам потрібен НОП, і :це. Решта виконують дії, які зовнішня команда може легко виконати.

Отже, п'яту частину цих вбудованих не потрібно вбудовувати. Чому ж тоді? Сторінка керівництва * на насправді пояснює мимохідь , чому це (увага вбудовані функції шахтні):dash

Вбудовані
 У цьому розділі перелічені вбудовані команди, які вбудовані, оскільки вони
 потрібно виконати деяку операцію, яку не можна виконати окремим
 процес. На додаток до них, можливо , є ще кілька команд
 бути вбудованим для ефективності (наприклад, printf (1), echo (1), test (1) тощо).

Це майже все: ці вбудовані елементи існують, тому що вони використовуються так часто, інтерактивно та в сценаріях, а їх функціональність досить проста, що оболонка може виконати роботу. І так буває: деякі (?) Більшість снарядів взяли на роботу ** Поверніться. З 2.9 BSD , і ви не знайдете вбудовану команду.shecho

Таким чином, цілком можливо, що мінімальна оболонка може пропустити реалізацію таких команд, як вбудовані (я не думаю, що жодна поточна оболонка робить). Проект coreutils GNU не передбачає, що ви збираєтеся запускати їх у певній оболонці, а POSIX вимагає цих команд. Отже, coreutils надає це все-таки і пропускає ті, які не мають жодного значення поза оболонкою.


* Це майже ідентично відповідному тексту сторінки для оболонки Almquist , на чому базується тире, оболонка Dex Almquist.

** zshдоводить цю ідею до кінця: команди, які ви отримуєте, завантажуючи різні модулі, наприклад zmv, - це речі, до яких ви б не думали, що оболонці навіть не потрібно потрапляти . Тоді справжнє питання: чому б ви використовували bash замість zsh, який має всі ці вбудовані?


1
Виявляється, що: також не потрібно бути вбудованим. Це просто нерозумно, щоб не бути вбудованим. Якщо ви не маєте справу з ранніми проблемами рівня init рятувальної дискети (в такому випадку я виявив, що складний спосіб pwd також не працює надійно), єдиний штраф за те, що це не є вбудованим, - жахлива ефективність.
Джошуа

5
@Joshua ні, :так як зовнішній насправді не був би NOP, у вас все одно буде PATHпошук, спроба виконання команди тощо. Коли все, що ви дійсно хочете, - це явно нічого не робити. :як вбудований робить це.
muru

2
Bash насправді потрібно pwdвбудовувати, щоб він працював так, як це робиться, за поведінкою за замовчуванням показує "логічний" шлях ( pwd -L). /bin/pwdміг реалізувати лише pwd -Pповедінку, показуючи вам фактичні батьківські каталоги, а не символьне посилання, яке ви cdредагували.
Пітер Кордес

2
Статус @PeterCordes pwdдещо погіршений наявністю PWD, але так, це також примірник bash, що використовує вбудований статус для поліпшення функціональності
muru
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.