xdotool: How to search for window by title and class with different patterns (similar to AutoHotkey)

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.


I was able to identify short and unix-way solution:

comm -12 \
  <(xdotool search --name  'title-pattern'  | sort) \
  <(xdotool search --class 'class-pattern'  | sort)

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

  1. has a linear structure, instead of a tree structure, like one instead of two dimensions
  2. uses more well known shell syntax.
  3. 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!