xdotool: How to search for window by title and class with different patterns (similar to AutoHotkey)
Solution 1
My xdotool help informs me that your two switches are the same (xdotool version 3.20150503.1),
--name check regexp_pattern agains the window name
--title DEPRECATED. Same as --name.
and as such doesn't do anything. My xdotool does the same as yours with replacing the window stack, so I did it with a shell script. A shell script doing what you want is delivered below:
pids=$(xdotool search --class "gvim")
for pid in $pids; do
name=$(xdotool getwindowname $pid)
if [[ $name == *"TODO"* ]]; then
#Do what you want, $pid is your sought for PID,
#matching both class gvim and TODO in title
fi
done
The asterisks in the if statement is there in order to do a substring match for TODO
, so that it can occur wherever in the title.
Solution 2
I was able to identify short and unix-way solution:
comm -12 \
<(xdotool search --name 'title-pattern' | sort) \
<(xdotool search --class 'class-pattern' | sort)
Solution 3
Here is another solution adhering to the UNIX way!
On first sight, it is not as beautiful as yours, @t7ko:
xdotool search --onlyvisible --class 'gvim' getwindowpid %@ | uniq | xargs -I{} xdotool search --all --pid {} --name 'TODO' getwindowgeometry | sed -r -n 's/.*Position: ([-0-9,+x]+) .*/\1/p'
But bear with me! There is some hidden beauty in it.
In short, it
- has a linear structure, instead of a tree structure, like one instead of two dimensions
- uses more well known shell syntax.
- does actually answer your question: It locates the window.
(Whether these points are advantages depends on context - let's just ignore this aspect*.)
I will show the same code in more structured layout below, to make it easier to understand step by step.
But note the indentation is to explain the command - it does not indicate nesting or so, all is still a linear UNIX pipeline.
The same command, just split after the pipes (|
): (uniq
left out)
xdotool search --onlyvisible --class 'gvim' getwindowpid %@ |
xargs -I{} xdotool search --all --pid {} --name 'TODO' getwindowgeometry |
sed -r -n 's/.*Position: ([-0-9,+x]+) .*/\1/p'
The full command, as shown above, gives the pixel location of the gvim
window, returning pixel coordinates relative to the top left corner of the current (possibly virtual) screen as x,y
, like 42,433
, or maybe -5375,-3809
when it's on the first of four by four virtual screens, and the current one is somewhere down on the right side.
For now, I will shorten the command to only find a X11 window ID - maybe that is all what was actually needed by the OP, not sure:
The shortened command pipeline, a separate shell command on each line:
xdotool search --onlyvisible --class 'gvim' getwindowpid %@ |
xargs -I{} xdotool search --all --pid {} --name 'TODO'
Now, it starts to be readable:
xdotool \
search --onlyvisible --class 'gvim' \
getwindowpid %@ |
xargs -I{} \
xdotool search --all --pid {} --name 'TODO'
The xdotool
command search
is used to find windows with the "class" gvim
, leaving out some "internal" windows. The result is listed as PID
's (process identifiers).
For each PID
, xargs
runs another xdotool search
, checking the "name" for our example pattern TODO
- after checking for the PID
.
(Just in case: The lines ending in \
- called continuation lines - need to actually end with the \
and no whitespace before the newline.)
Now back to the original command:
xdotool \
search --onlyvisible --class 'gvim' \
getwindowpid %@ |
xargs -I{} \
xdotool \
search --all --pid {} --name 'TODO' \
getwindowgeometry |
sed -r -n 's/.*Position: ([-0-9,+x]+) .*/\1/p'
The remaining part lists some details about the window, including the position. The sed
command matches and returns only the x,y
position value.
As example, running the command on the top on my 16th virtual screen (of 4 by 4), with a "TODO" gvim
on screen 1:
$ xdotool search --onlyvisible --class 'gvim' getwindowpid %@ | uniq | xargs -I{} xdotool search --all --pid {} --name 'TODO' getwindowgeometry | sed -r -n 's/.*Position: ([-0-9,+x]+) .*/\1/p'
-7653,-4732
*) Disclaimer: I prefer @t7ko's code. A lot!
Solution 4
Short and elegant answer (which uses wmctrl
):
result=$(wmctrl -l | grep 'TODO - gvim' | grep -Eo '0x[0-9a-f]+')
The resulting window ID is in hex, so you need to convert it to decimal (used by xdotool
):
printf "%d\n" $result
Then you can do whatever with xdotool
.
Related videos on Youtube

t7ko
Updated on September 18, 2022Comments
-
t7ko 9 months
xdotool lets you search for windows using its search subcommand. I need to locate a window, that has class 'gvim' and title containing word 'TODO'. How do I do this?
What I've tried:
- You can do
xdotool search --name --class
, but it would only accept one pattern for both name and title. - xdotool supports command chaining, but I could not find a way to chain two search calls -- the second one simply overrides first one.
- You can do
-
t7ko over 7 yearsyeah, sorry, a misprint, I meant --name and --class. Will fix now.
-
Gonki over 5 years@D.S may you tell why xdotool search --class "gedit" would now work for gedit only, but work for any other window? Same story with xprop utility.
-
t7ko about 5 years
wmctrl
manual says that-l
does not print window class, only title; so your code snippet does not solve my problem "search by title AND class". -
gokhan acar almost 5 yearsUsing
--onlyvisible
is nice. Helped me with a similar issue. Thunderbird can start with 14 windows and only one or two are on the desktop. I have no idea what the other ones are for. BTW only visible means can be displayed - not just immediately shown on the current desktop. -
david.perez almost 5 years
wmctrl -lx
does provide the class. -
Shanness almost 3 yearsJust a tip for anyone using this, it's 6x faster for me with a uniq to avoid duplicating the 2nd search
xdotool search --onlyvisible --class "Google-chrome" getwindowpid %@ | uniq | xargs -I{} xdotool search --all --pid {} --name ""todoist"
-
Volker Siegel almost 3 years@Shanness Right, thank you! I added it.
-
FantomX1 over 2 yearsthis is a way to go, lovely, I lost this reply but found it again, so have to comment