Вопрос или проблема
У меня есть скрипт, который открывает новое окно терминала, и я хочу переместить его в определенное положение на левом терминале с помощью xdotool.
После открытия терминала я выполняю
xdotool search --class gnome-term
и использую возвращенный идентификатор окна в командах xdotool windowsize и windowmove, чтобы изменить размер и положение нового окна терминала.
xdotool windowsize $WIN_ID 1978 407
xdotool windowmove $WIN_ID -26 702
Поскольку у меня запущено несколько терминалов, мне нужно определить, какому идентификатору окна WIN_ID соответствует только что созданное окно терминала.
В скрипте я выполняю следующую команду перед запуском нового терминала, чтобы получить список существующих идентификаторов WIN_ID.
for i in `xdotool search --class gnome-term`; do id_list="$id_list $i"; done
Пример содержимого $id_list:
65011713 65011722 65103242 65019818 65029314 65027106
После запуска нового терминала, чтобы определить новый WIN_ID, я выполняю этот тест.
for WID in `xdotool search --class gnome-term`; do if [[ ! $WID =~ $id_list ]]; then echo "Новый идентификатор окна = $WID"; fi; done
Когда я запускаю эту команду, вместо того чтобы получить только один (новый) идентификатор окна, я получаю все идентификаторы окон, связанные с классом gnome-terminal. Почему следующая команда не возвращает только WID, который не находится в id_list?
if [[ ! $WID =~ $id_list ]]; then ...
Скрипт:
...
...
# Создание списка идентификаторов окон для существующих окон gnome-terminal
for i in `xdotool search --class gnome-term`; do id_list="$id_list $i"; done
# Открытие нового окна терминала
gnome-terminal
# Получение идентификатора окна нового терминала
New_WID=`for WID in `xdotool search --class gnome-term`; do if [[ ! $WID =~ $id_list ]]; then echo $WID; fi; done`
...
...
Спасибо за ваше время и отзывы!
Текс
Если вы хотите найти идентификаторы окон, которые появились с момента последнего запуска xdotool search --class gnome-term
, по сути, это операция вычитания списков.
Это можно сделать, например, с помощью:
#! /bin/zsh -
die() { print -ru2 -C1 -- "$@"; exit 1; }
before=( $(xdotool search --class gnome-term) )
gnome-terminal
after=( $(xdotool search --class gnome-term) )
new_wid=( ${after:|before} )
(( $#new_wid == 1 )) || die "$#new_wid найден новый window${new_wid[2]+s}"
xdotool windowsize $new_wid 1000 500 $new_wid 12582932 -26 702
Если вам нужно использовать bash, в котором нет оператора вычитания списков, вы можете использовать comm
для этого:
#! /bin/bash -
println() { [ "$#" -eq 0 ] || printf '%s\n' "$@"; }
die() { println >&2 "$@"; exit 1; }
before=( $(xdotool search --class gnome-term | sort) )
gnome-terminal
after=( $(xdotool search --class gnome-term | sort) )
new_wid=( $(comm -13 <(println "${before[@]}") <(println "${after[@]}")) )
(( ${#new_wid[@]} == 1 )) ||
die "${#new_wid[@]} новый window${new_wid[1]+s} найден"
xdotool windowsize "$new_wid" 1978 407 "$new_wid" 12582932 -26 702
Ответ или решение
Для решения проблемы с идентификацией нового идентификатора окна (WIN_ID) в вашем bash-скрипте, существует несколько моментов, на которые стоит обратить внимание. Давайте разберем ваш код и предложим его оптимизированную версию.
Проблематика
Ваша текущая попытка проверить, является ли WIN_ID новым, основана на использовании регулярного выражения с оператором =~
. Однако переменная $id_list
, содержащая список ранее открытых окон, не работает так, как вы ожидаете, когда используется в условии. Это связано с тем, что оператор =~
ожидает регулярное выражение, а не строку с пробелами.
Решение
Для более эффективного и надежного решения можно использовать встроенные возможности bash
, такие как массивы, и команду comm
для сравнения массивов, если вы не против использовать внешние команды.
Вот улучшенная версия вашего скрипта:
#!/bin/bash
# Функция для вывода ошибок и выхода из скрипта
die() { echo "$@" >&2; exit 1; }
# Сохраняем список идентификаторов окон до запуска нового терминала
before=($(xdotool search --class gnome-terminal | sort))
# Запускаем новый терминал
gnome-terminal &
# Ждем, пока новый терминал появится
sleep 1
# Сохраняем список идентификаторов окон после запуска
after=($(xdotool search --class gnome-terminal | sort))
# Находим новый идентификатор окна с помощью comm
new_wid=($(comm -13 <(printf '%s\n' "${before[@]}") <(printf '%s\n' "${after[@]}")))
# Проверяем, найден ли только один новый идентификатор окна
if [[ ${#new_wid[@]} -ne 1 ]]; then
die "${#new_wid[@]} новых окна(ов) найдено. Ожидался один."
fi
# Изменяем размеры и позицию нового окна
xdotool windowsize "${new_wid[0]}" 1978 407
xdotool windowmove "${new_wid[0]}" -26 702
echo "Новое окно с ID=${new_wid[0]} успешно перемещено и изменено."
Основные изменения в скрипте:
-
Использование массивов: Мы сохраняем список идентификаторов окон как массивы до и после запуска нового терминала. Это упрощает сравнение.
-
Команда
comm
: Эта команда удобна для поиска различий между двумя отсортированными файлами или выводами, что облегчает задачу нахождения новых идентификаторов окон. -
Проверка количества новых окон: Мы явно проверяем количество найденных новых идентификаторов окон и выводим соответствующее сообщение об ошибке, если это не соответствует ожиданиям.
-
Добавлен
sleep 1
: Это дает пару секунд, чтобы новый терминал успел появиться в системе, что может помочь избежать проблем с мгновенным извлечением идентификатора окна.
Теперь скрипт должен корректно находить и обрабатывать новые идентификаторы окон gnome-terminal. Пожалуйста, протестируйте его и сообщите, если возникнут дополнительные вопросы.