whileループは変数の更新を覚えていないようです。関連パイプはありません。

whileループは変数の更新を覚えていないようです。関連パイプはありません。

標準のMateデスクトップを使用してLMDE 2(「Betsy」)を実行しており、次のスクリプトがあります。

#!/bin/bash
# This script starts a specified terminal-binary in "Always on Top"-mode
# The assumption is, that 'wmctrl -l' sorts windows with the 
# in such a way, that the more recently a window has been created, 
# the lower it will be on the list ( compared to windows with the 
# same title).
#
# This is my assumption based on a short observation. The window 
# ids are probably given out in ascending hex numbers
# 
# Note: Using the pid will not help, since all terminals seem to
# be having the same pid
term_title_def='Terminal'
term_title='Terminal_top'
term_cmd="mate-terminal --title=$term_title"

# start terminal, wait for window  to appear and get id of most recently created window
# NOTE: a possible wrap-around of window ids has not been considered here!
eval $term_cmd
win_id=''
while [[ -z $win_id ]]; do
    win_id=$(wmctrl -l | grep "[[:blank:]]$term_title\$" | tail -n 1 | awk '{ print $1 }')
done

# DEBUG
touch /tmp/$win_id

# rename, set as "Always on top"
wmctrl -ir $win_id -T "$term_title_def"
wmctrl -ir $win_id -b add,above
wmctrl -ia $win_id

ps aufx再起動後に初めてMATEパネルリンクからスクリプトを実行すると、スクリプトはwhileループを終了しません(検査を使用)。その後の呼び出しは期待どおりに機能します。つまり、リンクは私が望むように動作します(上記のスクリプトコメントを参照)。

win_idだからなぜかMATEを起動した後 -testが正しく拡張されていないようです(?) 。whileまたはそのようなもの。

なぜそんなことですか?
今同様のことを試してみましょうwhile true; do stuff; break; done。効果がありますように。

アップデート:上記の
ループを次のように交換してください。while

while true; do
    win_id=$(wmctrl -l | grep "[[:blank:]]$term_title\$" | tail -n 1 | awk '{ print $1 }')
    [[ $win_id ]] && break
done

何も変えませんでした。スクリプトはまだ無限ループに閉じ込められます...

答え1

私はこれがどのように機能するのか理解していません。走るとき

eval $term_cmd 

ターミナルウィンドウを開くと、それを閉じるまでスクリプトは他の操作を実行しません。あなたに必要なもの:

$term_cmd &

バックグラウンドで実行してください(eval必須ではないので使用しないでください)。これにより、wmctrl出力の最後の行も選択する必要はありません。端末のタイトルを設定しているので、これを唯一のものにしてくださいgrep

#!/bin/bash
# This script starts a specified terminal-binary in "Always on Top"-mode
# The assumption is, that 'wmctrl -l' sorts windows with the 
# in such a way, that the more recently a window has been created, 
# the lower it will be on the list ( compared to windows with the 
# same title).
#
# This is my assumption based on a short observation. The window 
# ids are probably given out in ascending hex numbers
# 
# Note: Using the pid will not help, since all terminals seem to
# be having the same pid
term_title_def='Terminal'
term_title="Terminal_top_$$" ## Use the script's PID for a unique title
term_cmd="mate-terminal --title=$term_title"

## Start terminal. No need to wait, the loop will run until
## the terminal has been opened
$term_cmd &

win_id=''

while [[ -z "$win_id" ]]; do
    ## No need for '[[:blank:]]' and \$, you are using a unique title,
    ## keep the regex general. 
    win_id=$(wmctrl -l | grep "$term_title" | awk '{ print $1 }')
done
# DEBUG
touch /tmp/$win_id

# rename, set as "Always on top"
wmctrl -ir $win_id -T "$term_title_def"
wmctrl -ir $win_id -b add,above
wmctrl -ia $win_id

答え2

whileループはサブシェルで実行されるため、サブシェルの変数に対する変更は親シェルには報告されません。https://stackoverflow.com/questions/16854280/modifying-variable-inside-while-loop-is-not-remembered

私の側の2番目の質問は次のとおりです。

$ while true; do toto=plop; echo $toto; [[ $toto ]] && break ; done 
plop

$win_idしたがって、ループ内の定義に実際の問題があると思います。

関連情報