How can I close all opening windows with a script?

Solution 1:

You might want to use wmctrl -c. If you're trying to close gedit for example, it will ask you if you want to save unsaved files.

WIN_IDs=$(wmctrl -l | awk '$3 != "N/A" {print $1}')
for i in $WIN_IDs; do wmctrl -ic "$i"; done

Solution 2:

Difficult problem, but I tricked it :) I searched a lot in the web and I resulted to a solution.

The following bash script, initially, reads all the open windows' IDs, then, it converts every of the IDs to process PIDs. Finally, it converts all the PIDs to process-names. It outputs both the PIDs and the process-names.

Here is the script:

#!/bin/bash
#Script by the whole web. I wrote it but it's not mine
#creating a temp file
temp1=$(mktemp)
#Getting all the windows' IDs and writing them to a file (CREDITS TO http://stackoverflow.com/questions/2250757/is-there-a-linux-command-to-determine-the-window-ids-associated-with-a-given-pro)
xwininfo -root -children|sed -e 's/^ *//'|grep -E "^0x"|awk '{ print $1 }' > $temp1;
#reading every window ID and converting it to a PID & writing it to a file... (CREDITS TO http://www.linuxquestions.org/questions/programming-9/getting-the-pid-of-the-top-active-window-776938/)
temp2=$(mktemp)
while read id; do
   xprop -id "$id" |  awk '/_NET_WM_PID\(CARDINAL\)/{print $NF}' >> $temp2
done < $temp1
#removing temp1
rm -f $temp1
#another temp file
temp3=$(mktemp)
#removing duplicate entries from $temp2 file: (CREDITS TO http://www.unix.com/shell-programming-scripting/20364-remove-duplicate-lines-file.html)
uniq $temp2 > $temp3
#removing temp2
rm -f $temp2
#!!! Outputting the PIDs: !!!
echo "The following PIDs were found:"
cat $temp3

#!!! Optional: getting their process names: !!! (CREDITS TO http://info.w3calculator.com/free-code/linux/how-to-get-process-name-from-pid/)
echo "The above PIDs have the following names:"
while read pid; do
   cat /proc/$pid/cmdline
   #newline
   echo
done < $temp3
#removing the last temp file...
rm -f $temp3

The output of this script on my machine, with ettercap-gtk open, chromium, 2 gnome-terminal windows and gedit, the output is:

The following PIDs were found:
9401
11194
1671
9401
10446
9401
10446
11194
10446
10434
9401
1653
1813
1671
1813
1454
1813
1653
1813
2340
2005
1996
1840
1809
1813
1809
1666
1781
1637
1773
1761
1653
1637
1653
1671
1669
1663
1653
1650
1649
1454
1400
1637
1653
1671
9401
The above PIDs have the following names:
/usr/lib/chromium-browser/chromium-browser
gedit/home/alex/Documents/macs
gnome-terminal-e/home/alex/Documents/WALLCH/start wait exec
/usr/lib/chromium-browser/chromium-browser
/usr/sbin/ettercap--gtk
/usr/lib/chromium-browser/chromium-browser
/usr/sbin/ettercap--gtk
gedit/home/alex/Documents/macs
/usr/sbin/ettercap--gtk
gksudo/usr/sbin/ettercap --gtk
/usr/lib/chromium-browser/chromium-browser
nautilus-n
/usr/lib/unity/unity-panel-service
gnome-terminal-e/home/alex/Documents/WALLCH/start wait exec
/usr/lib/unity/unity-panel-service
/usr/lib/gnome-settings-daemon/gnome-settings-daemon
/usr/lib/unity/unity-panel-service
nautilus-n
/usr/lib/unity/unity-panel-service
update-notifier
telepathy-indicator
/usr/lib/gnome-disk-utility/gdu-notification-daemon
/usr/lib/indicator-printers/indicator-printers-service
/usr/bin/gtk-window-decorator
/usr/lib/unity/unity-panel-service
/usr/bin/gtk-window-decorator
/home/alex/.dropbox-dist/dropbox
/usr/bin/gnome-screensaver--no-daemon
compiz
/usr/lib/bamf/bamfdaemon
/usr/lib/notify-osd/notify-osd
nautilus-n
compiz
nautilus-n
gnome-terminal-e/home/alex/Documents/WALLCH/start wait exec
bluetooth-applet
nm-applet
nautilus-n
/usr/lib/policykit-1-gnome/polkit-gnome-authentication-agent-1
/usr/lib/gnome-settings-daemon/gnome-fallback-mount-helper
/usr/lib/gnome-settings-daemon/gnome-settings-daemon
gnome-session--session=ubuntu
compiz
nautilus-n
gnome-terminal-e/home/alex/Documents/WALLCH/start wait exec
/usr/lib/chromium-browser/chromium-browser

As you can see, not only the open windows are being outputed, but also everything GUI-like, like nm-applet. So, if I were you, I would grep out every process that is obvious it shouldn't be killed, and then I would killall everything else!

You can also again 'uniq' so as to not kill duplicate things...

Solution 3:

Inspired by the answer given by user55822, I have made a script specifically to be used in the Xfce Desktop Environment, but it could be adapted to be used on any desktop using a window manager that interacts properly with wmctrl.

My script takes the extra step to wait until all the windows are actually closed so that if called from another script it won't return too soon. Here is my script for closing all the open windows other than panels and the Desktop itself:

WIN_IDs=$(wmctrl -l | grep -vwE "Desktop$|xfce4-panel$" | cut -f1 -d' ')
for i in $WIN_IDs; do wmctrl -ic "$i"; done

# Keep checking and waiting until all windows are closed 
while [ $WIN_IDs ]; do 
    sleep 0.1; 
    WIN_IDs=$(wmctrl -l | grep -vwE "Desktop$|xfce4-panel$" | cut -f1 -d' ')
done

To adapt it for a desktop other than Xfce, you would need to replace grep -vwE "Desktop$|xfce4-panel$" with whatever works on that desktop. What that part of the script is doing is narrowing down the results of wmctrl -l to not include anything ending in the word "Desktop" or "xfce4-panel". So to adapt it, you would just run wmctrl -l and look for what's at the end of the lines for windows you want to stay open. On Xfce at least, it ends up listing the Desktop itself as a window so that without the grep command, it ends up logging out of Xfce.