Server Fault is a question and answer site for system and network administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I am rsyncing a few directories. I have a bash terminal open and am executing something like this:

for DIR in * ; do rsync -a $DIR ; done

However if I want to stop the whole things, I press Control-C. That stops the rsync, but then it keeps going to the next one. In this case I realize what has happened and then just press Control-C like a madman until things work again.

Is there some way to 'fix' this. I want it so if I have a loop like that, and press Control-C, that it will return me to my bash shell.

share|improve this question
Dennis' answer is the right one, but you if you didn't do that, you don't have to 'press it like a madman', just hold it and let the keyboard repeat handle it :-) – Kyle Brandt Jan 22 '10 at 15:52
I always just hold down Cntl-C, generally works fine. – Scott Alan Miller Jan 22 '10 at 18:41
up vote 22 down vote accepted
for DIR in * ; do rsync -a $DIR || break; done

This will also exit the loop if an individual rsync run fails for some reason.

share|improve this answer
Fantastic, elegant, memorable solution. Thanks! – mmocny Jan 11 '13 at 16:32
Additional tip: if you're in a nested loop, and want to completely terminate, use break 2 (or replace "2" with the number of nested loops you want to terminate). – Dolan Antenucci Jan 23 '13 at 20:33

You can set a trap for Control-C.

trap command SIGINT

will execute the command when Control-C is pressed. Just put the trap statement somewhere in your script at a point where you want it to become effective.

share|improve this answer

To expand on Dennis' answer, your code might look like:

trap "echo Exited!; exit;" SIGINT SIGTERM

For a working example (that happens to involve rsync), check out

share|improve this answer

When you put a string of commands inside parentheses, the string will act as a single process, and will receive the SIGINT and terminate when you hit Ctrl-C:

(for DIR in * ; do rsync -a $DIR ; done)

But! In the case of the rsync command, it allows multiple sources, so the code you wrote would be better-written as:

rsync -a *
share|improve this answer
  1. Press Ctrl-Z to suspend the script ;
  2. kill %%

Credits, explanations and more details in this answer.

share|improve this answer

I tend to put another command in my loop that can easily be interrupted. It requires two ctrl-C's to be pressed.

for DIR in * ; do rsync -a $DIR ; sleep 1 ; done

It's not such a great solution for this rsync, which you probably want to run quickly. But it does work well for other loops, like this one:

while true ; do ping -c 10 ; sleep 1 ; done

This loop will re-lookup the address of every time through the loop, which is useful if you're watching for a DNS change.

share|improve this answer

Your Answer


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.