В bash
:
$ type :
: is a shell builtin
$ type true
true is a shell builtin
Выглядят они одинаково, но не дают одинаковой трассировки системы:
$ strace :
strace: :: command not found
$ strace true
execve("/bin/true", ["true"], [/* 82 vars */]) = 0
[snip]
exit_group(0) = ?
Я пробовал сравнивать strace bash -c : 2>:.txt
и strace bash -c true 2>true.txt
, но не смог найти никаких различий между ними, за исключением расположения памяти.
В dash
:
$ type :
: is a special shell builtin
$ type true
true is a shell builtin
Хорошо, значит, они не одинаковы. help :
и help true
не очень полезны, и они возвращают одно и то же в bash
и dash
. Есть ли между ними вообще какая-то практическая разница, кроме того, что это :
экономит три байта и делает скрипты менее читабельными?
решение1
Нет никакой реальной разницы в поведении. Обе команды ничего не делают и завершаются с успешным статусом. :
подчеркивает ничегонеделание; true
подчеркивает успешный статус.
strace true
работает, потому что true
это и встроенная команда оболочки, и внешняя команда ( /bin/true
); :
это только встроенная команда оболочки (нет /bin/:
-- хотя могла бы быть, и, вероятно, была в очень старых системах Unix). В bash попробуйте
type -a :
type -a true
Причины, по которым существуют оба, исторические. Если я правильно помню, в некоторых очень ранних оболочках не было синтаксиса комментариев, поэтому :
вместо этого использовалась команда do-nothing.
В dash
. Просмотр исходного кода, доступного по адресу git://git.kernel.org/pub/scm/utils/dash/dash.git, показывает некоторые отличающиеся пути кода в eval.c
, но мне не удалось добиться какого-либо заметно отличающегося поведения, кроме слова special
в выводе type :
.
решение2
В Bash они идентичны. Посмотрите builtins/colon.def
исходный код Bash-4.2.
В вашей команде strace true
вы на самом деле запускаете двоичный файл /bin/true
вместо встроенного в bash true.
решение3
Разница между командами в том, что по определению :
этоспециальный встроенныйполезность, тогда как true
этообычный встроенныйутилита в оболочках, совместимых с POSIX.
Согласно спецификации POSIX,специальные встроенные функциирассматриваются немного по-другому, а именно:
Присвоение значений переменным, предшествующее вызову специальной встроенной утилиты, остается в силе после завершения работы встроенной утилиты; это не относится к обычной встроенной или другой утилите.
Это можно проиллюстрировать в оболочках, совместимых с POSIX, следующим образом:
$ VAR=FOO
$ VAR=BAR :
$ echo "$VAR"
BAR
$ VAR=FOO
$ VAR=BAR true
$ echo "$VAR"
FOO
Еще один аспект различия заключается в том, что:
Ошибка в специальной встроенной утилите может привести к аварийному завершению работы оболочки, выполняющей эту утилиту, в то время как ошибка в обычной встроенной утилите не приведет к аварийному завершению работы оболочки, выполняющей эту утилиту.
Пример кода в действии:
$ ( : > ""; echo "You won't see this!" )
sh: 1: cannot create : Directory nonexistent
$ echo "Exit code: $?"
Exit code: 2
$ ( true > ""; echo "Hello!" )
sh: 1: cannot create : Directory nonexistent
Hello!
$ echo "Exit code: $?"
Exit code: 0