
$ cmd='time sleep 2'
$ $cmd
bash: time: command not found
Что здесь происходит? Дело не в том, что встроенные функции оболочки не работают, потому что это работает:
$ cmd2='echo wef'
$ $cmd2
wef
Есть идеи?
Редактировать: Я нашел разницу:
$ type time
time is a shell keyword
Против:
$ type echo
echo is a shell builtin
Итак, теперь возникает вопрос: почему встроенная функция работает в строке, а ключевое слово — нет?
решение1
time
какGNU-башКлючевое слово имеет вполне определенное место, где оно принимается, см., например, синтаксис для конструкции конвейера команд:
Формат конвейера:
[time [-p]] [!] command1 [| command2 ...]
Это жестко задает положение ключевого слова вне расширений (каккомандаNбудет там, где будут развернуты параметры и переменные). Фактически, семантика также применяется ко всему конвейеру, а не к команде, поэтому, вероятно, это должно быть ключевое слово.
Есть встроенная оболочка times
(в POSIXспециальный встроенный), для этого расширение работает, поскольку первое слово может быть исполняемым файлом или встроенной оболочкой.
АльтернативноGNU coreutils содержит /bin/time
исполняемый файл.
На самом деле time
нетзарезервированное слововОболочка POSIX(хотя bash распознает его врежим posixв любом случае (если только -
по неочевидным причинам не следует а)).
Внутри eval
выражения ключевые слова распознаютсяБаш, поэтому это можно использовать для динамического улучшения команд с помощью временного профилирования. (Однако, с другой стороны, это требует дополнительного раунда кавычек)
решение2
Вместо использования cmd='time sleep 2' попробуйте использовать его как cmd='/usr/bin/time sleep 2', чтобы получить команду реального времени.
В man time вы можете прочитать следующее:
Пользователям оболочки bash необходимо использовать явный путь для запуска внешней команды time, а не встроенного варианта оболочки. В системе, где время установлено в /usr/bin, первый пример будет выглядеть так: /usr/bin/time wc /etc/hosts