Count the minimized windows on Linux with bash - linux

I'm trying to build a script that checks that windows under XFCE are minimized before displaying a window I've chosen (it's a part from a bigger project)
I tried to recover the count of the open windows with wmctrl
but these are not the minimized windows :
CURRWORKSPACE=$(wmctrl -d | grep '*' | cut -d ' ' -f1)
OPENWINDOWS=$(wmctrl -l | cut -d ' ' -f3 | grep $CURRWORKSPACE | wc -l)
I also try with xdotool, but without success :(
I was wondering if you knew of any way to get this information.
I'm on XFCE, but another way with any tool would be great
Many thanks !

Given a window and its id as listed by wmctrl you can use the following function to determine whether that window is minimized. Note that minimized windows are called iconic in X.
# usage: isMinimized <windowId>
# returns status 0 if and only if window with given id is minimized
isMinimized() {
xprop -id "$1" | grep -Fq 'window state: Iconic'
}
In order to count open windows you can loop over the list of window ids.
openWindows() {
count=0
for id in $(wmctrl -l | cut -f1 -d' '); do
isMinimized "$id" || ((count++))
done
echo $count
}
At least on my desktop environment (Cinnamon) some "windows" were always open. These windows are for instance the Desktop. I adjusted the function by filtering out these windows before looping over them. Since they were sticky and I normally don't use sticky windows I just neglected all sticky windows: $(wmctrl -l | grep -vE '^0x\w* -1' | cut -f1 -d' ').
You can adjust the filtering to your needs. In this case all open and non-sticky windows on all workspaces/desktops are counted.

Related

How can I query the number of the virtual desktop on which the bash script is running in Linux Mint via bash?

Environment:
Linux Mint, Cinnamon desktop manager, with multiple workspaces=virtual desktops, e.g. 4.
Bash script
What is known:
How to determine the number of workspaces:
wmctrl -d | wc -l
What I need:
Get the number of virtual desktops the bash script is running on with a pure bash as var (like with grep, not awk or similar) and echo the var.
With awk (imho still the most appropriate choice for the task at hand):
nr_of_active_workspace=$(wmctrl -d | awk '/\*/{print $NF}')
echo $nr_of_active_workspace
Or a pure bash solution:
nr_of_active_workspace=$(wmctrl -d | while read -r line; do [[ $line =~ '*' ]] && echo ${line: -1} ; done)
echo $nr_of_active_workspace
You can use POSIX shell features and the xprop(1) command to get both details with no other external utilities.
To get the ID number of the current/active desktop:
curdesk=$(xprop -root -notype _NET_CURRENT_DESKTOP)
curdesk="${curdesk##* }"
To get the count/quantity of desktops defined:
deskcnt=$(xprop -root -notype _NET_NUMBER_OF_DESKTOPS)
deskcnt="${deskcnt##* }"
Both depend on xprop(1) giving the answer in the form "foo = 0" (separated by spaces), and use shell pattern matching parameter expansion to match the longest substring ending in space, and remove it, leaving only the last token (the value after the equals sign).
Note that desktops are numbered from 0 (zero), so the count will be a number one higher than the ID number of the last desktop.
This should work with any window manager that adheres to the Extended Window Manager Hints (EWMH) specification (which is practically all of them, these days):
https://specifications.freedesktop.org/wm-spec/1.3/ar01s03.html
Follow a solution which need awk:
nr_of_active_workspace=$(wmctrl -d | grep "*" | awk '{print $11}')
echo $nr_of_active_workspace
It can be a solution without need awk, are possible on other way.
Based on answer of KamilCuk, its possible to output on follow way the line which is including the number of the active desktop:
nr_of_active_desktop=activedesktop=$(wmctrl -d | grep "*" | rev | cut -d ' ' -f1)
echo $nr_of_active_desktop

How to extract field from command result in different versions of linux?

I was trying to extract a process size using the command:
size=`ps -eo vsz,pid | grep $pid | cut -'d' -f1`
However, this appeared to only work on some computers but not all. So on the ones where it wasn't working, I tried:
size=`ps -eo vsz,pid | grep $pid | awk '{print $1}'`
however, now this didn't work on the computers where the first command worked.
What I mean by "working" and "not working" is that sometimes:
echo "|$size|"
Will return something like:
|8762348
9835|
And thus the following returns an arithmetic error:
(( $size > $threshold ))
because of the newline or carriage return characters stored in $size. Is there a way to reliable extract simply the first field across different versions of linux?
First you ask ps to displat info for all processes, next you try to select 1 of them.
Your command had problems on some computers, and you tagged the question with both ksh and linux, so I am not sure what command can be used best in your case:
size=$(ps -q ${pid} -o vsz --no-headers)
# or
size=$(ps -p ${pid} -o vsz | grep -v "VSZ")

Extract multiple substrings in bash

I have a page exported from a wiki and I would like to find all the links on that page using bash. All the links on that page are in the form [wiki:<page_name>]. I have a script that does:
...
# First search for the links to the pages
search=`grep '\[wiki:' pages/*`
# Check is our search turned up anything
if [ -n "$search" ]; then
# Now, we want to cut out the page name and find unique listings
uniquePages=`echo "$search" | cut -d'[' -f 2 | cut -d']' -f 1 | cut -d':' -f2 | cut -d' ' -f 1 | sort -u`
....
However, when presented with a grep result with multiple [wiki: text in it, it only pulls the last one and not any others. For example if $search is:
Before starting the configuration, all the required libraries must be installed to be detected by Cmake. If you have missed this step, see the [wiki:CT/Checklist/Libraries "Libr By pressing [t] you can switch to advanced mode screen with more details. The 5 pages are available [wiki:CT/Checklist/Cmake/advanced_mode here]. To obtain information about ea - '''Installation of Cantera''': If Cantera has not been correctly installed or if you do not have sourced the setup file '''~/setup_cantera''' you should receive the following message. Refer to the [wiki:CT/FormulationCantera "Cantera installation"] page to fix this problem. You can set the Cantera options to OFF if you plan to use built-in transport, thermodynamics and chemistry.
then it only returns CT/FormulationCantera and it doesn't give me any of the other links. I know this is due to using cut so I need a replacement for the $uniquepages line.
Does anybody have any suggestions in bash? It can use sed or perl if needed, but I'm hoping for a one-liner to extract a list of page names if at all possible.
egrep -o '\[wiki:[^]]*]' pages/* | sed 's/\[wiki://;s/]//' | sort -u
upd. to remove all after space without cut
egrep -o '\[wiki:[^]]*]' pages/* | sed 's/\[wiki://;s/]//;s/ .*//' | sort -u

How do I get xid from pid (and vice versa)?

How do I get the pid from the xid (X window identifier)? How do I get the list of xids for a given pid?
(Assuming all applications run with DISPLAY=:0, without network transparency being in use)
I'm expecting something like:
Dig in /proc/$pid/fd/ to track connection to X server
Follow that connection, dig in /proc/`pidof X`/fd
Dig inside X as it should know how to map connections to it to windows.
You could use xprop -id <windowid> _NET_WM_PID to get the PID property of the window in question. You should know the window id of the window and not all applications set the _NET_WM_PID atom.
This works for my purposes:
=^_^= izkata#Izein:~$ XID=0x340001c
=^_^= izkata#Izein:~$ printf "%d\n" $XID # Convert from hex to decimal
54525980
=^_^= izkata#Izein:~$ xdotool getwindowpid 54526066
20639
=^_^= izkata#Izein:~$ ps 20639
PID TTY STAT TIME COMMAND
20639 ? Ssl 116:25 /usr/lib/firefox/firefox
wmctrl lists windows, their xids and optionally the pid of their process. So assuming there is only one window with your $pid, you could get the corresponding xid with
wmctrl -ulp | tr -s ' ' | cut -d" " -f1,3 | grep $pid | cut -d" " -f1
and conversely, assuming the xid is in hexa,get the pid
wmctrl -ulp | tr -s ' ' | cut -d" " -f1,3 | grep $xid | cut -d" " -f2
.

Manipulate window size in linux via compiled code?

I wrote a couple of scripts to maximize a window to half the size of the screen (to make it easy to place windows side-by-side) using xrandr, grep, and wmctrl as follows:
#!/bin/bash
w=`xrandr 2> /dev/null | grep '*' | grep -Po '\d+(?=x)'`
h=`xrandr 2> /dev/null | grep '*' | grep -Po '(?<=x)\d+'`
wmctrl -r :ACTIVE: -b remove,maximized_horz,maximized,vert
wmctrl -r :ACTIVE: -e 0,0,0,$((w / 2)),$h
Is there a way to do this more natively? The script works well on my desktop, but on my laptop there's a half-second lag that is kind of annoying.
test code
# w_h="$(print -- "1280x1024 0.0*" | awk '/.*\*$/{sub(/ .*$/, "");sub("x"," ");$1=$1/2 ;print}')"
# w="${w_h% *}" ; h="${w_h#* }"
actual code
# awk matches only line ending with '*', remove everything from last space to EOL, replace X with " "
# w_H looks like "640 1040", below splits on space char populating correct var
w_h="$(xrandr | awk '/\*/{sub(/[0-9\.*\+]*$/, ""); sub("x", " "); $1=$1/2; print}')"
w="${w_h% *}" ; h="${w_h#* }"
wmctrl -r :ACTIVE: -b remove,maximized_horz,maximized,vert
wmctrl -r :ACTIVE: -e 0,0,0,${w},${h}
Note that I have done the div on W inside awk. Also, backticks are deprecated in posix shells. Make your life easier and use $() for command substituton ;-)
I hope this helps.

Resources