Встроенное в строку время Bash не выполняется

1
$ cmd='time sleep 2'
$ $cmd
bash: time: command not found

Что тут происходит? Дело не в том, что встроенные оболочки не работают, потому что это работает:

$ cmd2='echo wef'
$ $cmd2
wef

Есть идеи?

Изменить: я нашел разницу:

$ type time
time is a shell keyword

Vs:

$ type echo
echo is a shell builtin

Теперь возникает вопрос: почему встроенная функция работает в строке, а ключевое слово - нет?

ACK_stoverflow
источник
1
Обе команды работают как положено для меня. Какой выход which time? Возможно, вы не установили timeкоманду.
Стивен
Вау, ты прав, @Steven. Я думал, что вместо этого должны быть двойные кавычки ... но это действительно работает. Может быть, это проблема $ PATH!
JVB
timeявляется частью bash, у меня нет timeустановленного двоичного файла.
ACK_stoverflow
2
Ключевые слова оболочки не оцениваются после раскрытия. Вам нужно будет использовать / bin / time или использовать eval.
eckes
1
@eckes Ты выиграл. Черт, какой странный маленький гоча. Напиши свой комментарий как ответ и я приму.
ACK_stoverflow

Ответы:

2

timeпоскольку ключевое слово GNU Bash имеет очень конкретное место, где принимается, см., например, синтаксис для конструкции конвейера команд:

Формат для конвейера [time [-p]] [!] command1 [| command2 ...]

Это жестко закодирует позицию ключевого слова вне расширений (поскольку команда N будет там, где раскрываются параметры и переменные). Фактически, семантика применяется ко всему конвейеру, а не к команде, поэтому, вероятно, именно поэтому это должно быть ключевое слово.

Существует встроенная оболочка times(в POSIX - специальная встроенная ), для этого расширение работает, поскольку первое слово может быть исполняемым или встроенным в оболочку.

В качестве альтернативы GNU coreutils содержит /bin/timeисполняемый файл.

Фактически timeэто не зарезервированное слово в POSIX Shell (хотя bash в любом случае распознает его в режиме posix (если не -следует по неочевидным причинам)).

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

Экес
источник
0

Вместо использования cmd = 'time sleep 2' попробуйте использовать его как cmd = '/ usr / bin / time sleep 2', чтобы получить команду в реальном времени.

Вы можете прочитать следующее в man time:

Пользователи оболочки bash должны использовать явный путь для запуска внешней команды времени, а не встроенный вариант оболочки. В системе, в которой время установлено в / usr / bin, первым примером будет / usr / bin / time wc / etc / hosts

Дженаро Моралес
источник
Да, я бы пошел по этому пути для своего решения, но кажется, что / usr / bin / time не устанавливается по умолчанию в серверных системах Debian 8, поэтому вместо установки зависимости мне проще просто оценить.
ACK_stoverflow