Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

I was reading the O'Reilly book "Unix in a nutshell", and I saw there that commands can be grouped and executed in the current shell using the following format:

{ cmd1 ; cmd2 }

I didn't understand how this is possible, as I knew that a call to exec replaces a shell's data, and therefore the shell can't return from an exec system call. So I tested the command and I can't understand what happened. I entered into a command line and I'm not sure to what does the command line belong.

Is it just the terminal emulator's command line, stripped down from the shell?

Also, how is executing commands in the current shell in any way useful?

enter image description here

share|improve this question

3 Answers 3

up vote 4 down vote accepted

To exec or not to exec

a call to exec replaces a shell's data, and therefore the shell can't return from an exec system call.

But not every command is the name of a program to execute. So often there is no exec call involved. The key distinction is that in contrast to ( cmd1; cmd2; ), you don't get another shell process. Or perhaps more correctly, the shell will only fork to execute child programs, not to execute shell processes.

Strange prompt

what does the command line belong.

As other answers have pointed out, your command was incomplete. So the command line belonged to bash itself, which was waiting for the end of your group.

Uses

Also, how is executing commands in the current shell in any way useful?

… as opposed to subshell grouping

The most prominent example is setting variables in that subcommand. Thy this:

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

This will print

2
3
2

So although you set foo=3 inside one group, that group was executed in a subshell and its settings didn't propagate to the parent.

Another thing worth considering is current working directory. { cd foo; make; } will leave you in directory foo whereas ( cd foo; make; ) will not alter the current working directory of your main shell.

… as opposed to ungrouped commands

The grouping is mostly useful if you have other code outside, e.g. conditionals

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

or redirections

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

It is because you don't terminate the second line: { cmd1; cmd2; } is correct. The semicolon means "end of command".

share|improve this answer
    
You're right, thanks(maybe the book uses an old format). But how is resuming the shell possible if the commands are executed within it? Does the shell call fork? –  user3122885 Apr 1 at 11:07
    
The shell will be blocked until the command finishes. This is actually a good reason to use groups. For instance, when adding a PPA, you'll want to first add the repository information, then import keys, then update your cache and then install. If you paste it as a group, then everything will be run in order. If you don't, you'll have to input again because the shell is unable to receive your input. –  Jo-Erlend Schinstad Apr 1 at 11:24

The help builtin can be useful even for the { keyword. From help -m {:

NAME
    { ... } - Group commands as a unit.

SYNOPSIS
    { COMMANDS ; }

So, the semicolon (;) is mandatory after each command.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.