Bash Loop — как остановить цикл при нажатии Control-C внутри команды?

Bash Loop — как остановить цикл при нажатии Control-C внутри команды?

Я синхронизирую несколько каталогов. У меня открыт терминал bash, и я выполняю что-то вроде этого:

for DIR in * ; do rsync -a $DIR example.com:somewhere/ ; done

Однако если я хочу остановить все это, я нажимаю Control-C. Это останавливает rsync, но затем он продолжает переходить к следующему. В этом случае я понимаю, что произошло, и просто нажимаю Control-C как сумасшедший, пока все снова не заработает.

Есть ли способ «исправить» это? Я хочу, чтобы при возникновении такого цикла и нажатии Control-C я возвращался в оболочку bash.

решение1

for DIR in * ; do rsync -a $DIR example.com:somewhere/ || break; done

Это также приведет к выходу из цикла, если отдельный запуск rsync по какой-то причине завершится неудачно.

решение2

Чтобы расширить ответ Денниса, ваш код может выглядеть так:

trap "echo Exited!; exit;" SIGINT SIGTERM

Для рабочего примера (который, как оказалось, использует rsync) посмотритеhttp://gist.github.com/279849.

решение3

Вы можете устроить ловушку для Control-C.

trap <command> SIGINT

выполнит commandпри нажатии Control-C. Просто поместите оператор trapгде-нибудь в вашем скрипте в точке, где вы хотите, чтобы он вступил в силу.

решение4

Если вы поместите строку команд в скобки, строка будет действовать как единый процесс, получит сигнал SIGINT и завершится, когда вы нажмете Ctrl- C:

(for DIR in * ; do rsync -a "$DIR" example.com:somewhere/ ; done)

Но! В случае с rsyncкомандой она допускает несколько источников, поэтому код, который вы написали, лучше записать так:

rsync -a * example.com:somewhere/

Связанный контент