Kurt Peek
Kurt Peek

Reputation: 57761

How to close all terminals with a bash script that effectively presses Cntrl+Shift+Q in each terminal

I often have many terminals open, some of which are running important processes (e.g. servers) and others which are not running anything and can be closed. The 'important' ones bring up prompts for confirmation if you press Cntrl+Shift+Q in them, like the one shown below.

enter image description here

I would like to have a (bash) script which closes all terminals but leaves the 'important' ones in the mode shown above. From https://askubuntu.com/questions/608914/closing-all-instances-of-terminal-at-once-cleanly, I obtained the following script:

#!/bin/bash

xdotool search --class "terminal" | while read id
do
      xdotool windowactivate "$id" &>/dev/null
      xdotool key ctrl+shift+q
      sleep 0.2
done 

However, I found after running the script that some 'unimportant' terminals still remained open. Is there perhaps a bug in the script above?

Upvotes: 2

Views: 2333

Answers (1)

webb
webb

Reputation: 4340

another way to do this is to kill any idle bash processes, that is, those with no subprocesses. this should also close their parent terminal windows. it will run much faster than the xdotool + sleep 0.2 method.

here is how i can see process trees for my bash processes:

pgrep bash | xargs -r -n1 pstree -p -c

output:

bash(1470)───startx(1546)───xinit(1568)─┬─Xorg(1569)─┬─{Xorg}(1570)
                                        │            ├─{Xorg}(1571)
                                        │            └─{Xorg}(1572)
                                        └─dwm(1575)
bash(1582)
bash(4004)
bash(4125)
bash(28105)───nvim(17279)─┬─R(17956)─┬─{R}(17958)
                          │          ├─{R}(17959)
...

the first and last bashs here have subprocesses and i don't want to kill them. the middle three can safely be killed, which will also close their parent terminal windows. first, i'll select only those by filtering out any lines with a "-":

pgrep bash | xargs -r -n1 pstree -p -c | grep -v \-

output:

bash(1582)
bash(4004)
bash(4125)

next, i'll use grep again to include only the process id numbers:

pgrep bash | xargs -r -n1 pstree -p -c | grep -v \- | grep -o '[0-9]\+'

output:

1582
4004
4125

finally, kill them:

pgrep bash | xargs -r -n1 pstree -p -c | grep -v \- | grep -o '[0-9]\+' | xargs -r kill

Upvotes: 5

Related Questions