Bash – выполнение команд в текущей оболочке

Я читал книгу O'Reilly «Unix в двух словах», и я увидел там, что команды могут быть сгруппированы и выполнены в текущей оболочке, используя следующий формат:

{ cmd1 ; cmd2 } 

Я не понял, как это возможно, поскольку я знал, что вызов exec заменяет данные оболочки, и поэтому оболочка не может вернуться из системного вызова exec. Поэтому я протестировал команду, и я не могу понять, что произошло. Я вошел в командную строку, и я не уверен, что принадлежит командной строке.

Это просто командная строка эмулятора терминала, удаленная из оболочки?

Кроме того, каким образом выполнение команд в текущей оболочке полезно?

введите описание изображения здесь

Выполнять или не выполнять

вызов exec заменяет данные оболочки, и поэтому оболочка не может вернуться из системного вызова exec.

Но не каждая команда – это имя исполняемой программы. Так часто не задействован вызов exec . Основное отличие состоит в том, что в отличие от ( cmd1; cmd2; ) , вы не получаете другого процесса оболочки. Или, может быть, более правильно, оболочка будет только fork для выполнения дочерних программ, а не для выполнения процессов оболочки.

Странное приглашение

что принадлежит командной строке.

Как указывали другие ответы, ваша команда была неполной. Таким образом, командная строка принадлежала самому bash, который ждал конца вашей группы.

Пользы

Кроме того, каким образом выполнение команд в текущей оболочке полезно?

… в отличие от группировки подоболочек

Наиболее ярким примером является установка переменных в этой подкоманде. Вот так:

 foo=1; { foo=2; echo $foo; }; ( foo=3; echo $foo; ); echo $foo 

Это напечатает

 2 3 2 

Поэтому, хотя вы устанавливаете foo=3 внутри одной группы, эта группа была выполнена в подоболочке и ее настройки не распространялись на родителя.

Еще одна вещь, которую стоит рассмотреть – это текущий рабочий каталог. { cd foo; make; } { cd foo; make; } оставит вас в каталоге foo тогда как ( cd foo; make; ) не изменит текущий рабочий каталог вашей основной оболочки.

… в отличие от негруппированных команд

Группировка в основном полезна, если у вас есть другой код снаружи, например, условные

 test -f foo && { echo "Foo exists."; rm foo; } 

или перенаправления

 { echo "Content of $PWD:"; ls; } | gzip > dirlist.gz 

Это потому, что вы не завершаете вторую строку: { cmd1; cmd2; } { cmd1; cmd2; } { cmd1; cmd2; } является правильным. Точка с запятой означает «конец команды».

Встроенная help может быть полезна даже для ключевого слова { . Из help -m { :

 NAME { ... } - Group commands as a unit. SYNOPSIS { COMMANDS ; } 

Таким образом, точка с запятой ( ; ) является обязательной после каждой команды.