Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

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 example.com:somewhere/ ; 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
6  
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
add comment

5 Answers

up vote 12 down vote accepted
for DIR in * ; do rsync -a $DIR example.com:somewhere/ || 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
add comment

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
add comment

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 http://gist.github.com/279849.

share|improve this answer
add comment

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 example.com:somewhere/ ; 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 * example.com:somewhere/
share|improve this answer
add comment

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 example.com:somewhere/ ; 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 example.com ; sleep 1 ; done

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

share|improve this answer
add comment

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.