LinuxシェルスクリプトにGUIを追加する方法
公開: 2022-01-29
 Bashスクリプトでは、GUIウィンドウ、スライダー、ラジオボタン、プログレスバーなどを使用できます。 zenityツールキットの使用方法を学び、Bashスクリプトを改良します。 その方法をお見せします。
Bashスクリプトは強力なプログラミング言語であり、Bashシェルに組み込まれているため、誰でもすぐに利用できます。 プログラミングを始めるのは簡単な言語です。解釈されるため、スクリプトをコンパイルする必要はありません。 スクリプトファイルを編集して実行可能にするとすぐに実行できます。 これにより、コーディング、実行、およびデバッグのサイクルが非常に効率的になります。
Bashスクリプトに関して人々が抱く主な不満は2つあり、1つ目は速度です。 Bashシェルはスクリプト内のコマンドを解釈するため、コンパイルされたコードほど速く実行されません。 しかし、これはトラクターが車ほど速くないことを不平を言うようなものです。 それらはさまざまな目的のためのものです。
ただし、速度には2種類あります。 多くの場合、クイックスクリプトをまとめて使用すると、Cなどのコンパイル言語でソリューションを開発するよりもはるかに迅速にタスクを実行できます。
Bashスクリプトに関する2番目の不満は、ユーザーインターフェイスです。これはターミナルウィンドウです。 もちろん、インターフェースが重要でない場合もあります。 スクリプトを使用するのがその作成者だけである場合、インターフェイスはおそらくそれほど重要ではありません。 また、バックグラウンドおよびバッチタイプの処理を実行するスクリプトについても重要ではありません。 通常、このようなスクリプトは、(あるとしても)多くのユーザー操作を必要としません。
ターミナルウィンドウよりも少し直感的でモダンなものが必要な場合があります。 ほとんどの人は、グラフィカルユーザーインターフェイス(GUI)に精通しています。 できるだけ摩擦のないエクスペリエンスを人々に提供するには、スクリプトからGUI要素を作成して使用する必要があります。
zenityアプリケーション
zenityを使用すると、Bashスクリプトにさまざまなグラフィカルインターフェイス要素を組み込むことができます。 これは、スクリプトにモダンな雰囲気と現代的で親しみやすい外観を与える強力なツールキットです。
 zenityは、Ubuntu、Fedora、およびManjaroディストリビューションにプレインストールされています。 それはGNOMEの一部です。 KDEを使用している場合は、代わりにkdialogを確認することをお勧めしますが、 zenityはどのデスクトップ環境でも実行できます。
この記事の例では、コマンドラインからさまざまなダイアログウィンドウを作成する方法、変数でそれらの戻り値とユーザー選択をキャプチャする方法、およびスクリプトでダイアログウィンドウを使用する方法を示します。
最後に、3種類すべてのダイアログウィンドウを使用する小さなアプリケーションを作成します。
カレンダーダイアログウィンドウ
カレンダーダイアログウィンドウでは、誰かが日付を選択できます。 zenityで1つを作成するには、2つの単語の単一のコマンドが必要です。
zenity--calendar

カレンダーダイアログウィンドウが表示されます。 これには、標準の日付ピッカーに期待されるすべての機能があります。 月と年を変更し、日をクリックしてその日付を選択できます。 デフォルトでは、ウィンドウが表示されるときに今日の日付が強調表示されます。

「OK」をクリックしてダイアログウィンドウを閉じ、強調表示された日付を選択します。 日付をダブルクリックしても同じことができます。
日付を選択したくない場合は、「キャンセル」をクリックするか、キーボードの「Esc」キーを押すか、ダイアログウィンドウを閉じます。

上記の例では、2019年8月19日が選択されています。 ユーザーが「OK」をクリックすると、カレンダーが閉じ、選択した日付がターミナルウィンドウに印刷されます。

「一時的な親なしでマップされたGTKDialog」という行は無視してかまいません。 これはお勧めできません。」
GTKはGIMPTool Kitの略で、GNOMEインターフェースの開発に使用されるツールキットです。 もともとはGNUImage Manipulation Program(GIMP)の作者によって考案されました。 GNUはGNUのNotUnixの略です。
 GTKエンジンは、 zenityの作者に、GTKコンポーネントを非標準的な方法で使用したことを警告しています。
日付値の取得
ターミナルに日付を印刷しても、あまり効果はありません。 スクリプトの1つからこのカレンダーを呼び出す場合は、選択した日付の値をキャプチャして、スクリプトで何か役立つことができるようにする必要があります。 カレンダーも少しカスタマイズします。
カレンダーでは次のオプションを使用します。 これらはすべて、二重ダッシュの「–」フラグとともに使用する必要があります。
- –text :カレンダーに表示するテキストの文字列を指定します。 これは、デフォルトの「下から日付を選択」に置き換わるものです。
- –title :カレンダーダイアログウィンドウのタイトルを設定します。
- –day :カレンダーが開いたときに選択される日を設定します。
- –month :カレンダーが開いたときに選択される月を設定します。
- –year :カレンダーが開いたときに選択される年を設定します。
 カレンダーから返された日付をキャプチャするために、 ChosenDateという変数を使用しています。 そして、 echo $ChosenDateを使用して、その日付をターミナルウィンドウに出力しています。
はい、前の例でも同じ結果が得られましたが、ここでは、選択した日付が変数に格納されています。 前の例では、印刷されて忘れられていました。
ChosenDate = $(zenity --calendar --text "Choose a date" --title "How-To Geek Rota" --day 1 --month 9 --year 2019); エコー$ ChosenDate

これで、カレンダーにプロンプトとウィンドウタイトルが表示されます。 日付は、今日の日付ではなく、選択した開始日に設定されます。

 選択時に返される日付文字列の形式をカスタマイズすることもできます。 --date-formatオプションの後には、フォーマット指定子が続く必要があります。 これは、出力に含まれるデータとフォーマットを定義するトークンの文字列です。 トークンは、 strftime() C言語関数で使用されるものと同じであり、膨大な数のトークンがあります。
使用しているトークンは次のとおりです。
- %A :曜日のフルネーム。
- %d :数字としての月の日。
- %m :数字としての月。
- %y : 2桁の年(世紀なし)。
ChosenDate = $(zenity --calendar --text "Choose a date" --title "How-To Geek Rota" --date-format = "%A%d /%m /%y" --day 1- 9か月目-2019年); エコー$ ChosenDate

誰かが日付を選択します:

そして、日付は私たちのフォーマットを使用して返されます。 曜日の名前に続いて、ヨーロッパの順序で日付が表示されます:日、月、年。

[ファイルの選択]ダイアログウィンドウ:ファイルの選択
ファイル選択ダイアログウィンドウは非常に複雑です。 ユーザーはファイルシステムを参照し、1つまたは複数のファイルを強調表示してから、[OK]をクリックしてそれらのファイルを選択するか、選択を完全にキャンセルできます。
 zenityは、このすべての機能などを提供します。 また、カレンダーダイアログウィンドウと同じように簡単に使用できます。
使用する新しいオプションは次のとおりです。
-  –file-selection :ファイル選択ダイアログウィンドウを使用することをzenityに通知します。
- –複数:誰かが複数のファイルを選択できるようにします。
- –file-filter :表示するファイルタイプをファイルダイアログウィンドウに指示します。
zenity --file-selection --tile "How-To Geek" --multiple --file-filter = '* .mm * .png * .page * .sh * .txt'

ファイル選択ダイアログウィンドウは、他のファイル選択ウィンドウと同じように機能します。

ユーザーはファイルシステムを参照して、選択したファイルを選択できます。

新しいディレクトリを参照し、「button_hybrid.png」というファイルを選択しました。
「OK」をクリックすると、ファイル選択ダイアログウィンドウが閉じ、ファイル名とパスがターミナルウィンドウに表示されます。

今後の処理でファイル名を使用する必要がある場合は、カレンダーの日付の場合と同じように、ファイル名を変数に取り込むことができます。
[ファイルの選択]ダイアログウィンドウ:ファイルの保存
オプションを1つ追加すると、ファイル選択ダイアログウィンドウをファイル保存ダイアログウィンドウに変えることができます。 オプションは--saveです。 --confirm-overwriteオプションも使用します。 これにより、既存のファイルを上書きするかどうかを確認するように求められます。
Response = $(zenity --file-selection --save --confirm-overwrite); エコー$ Response

ファイル保存ダイアログウィンドウが表示されます。 誰かがファイル名を入力できるテキストフィールドがあることに注意してください。

ユーザーは、ファイルシステム内で選択した場所を参照したり、ファイルの名前を指定したり、既存のファイルをクリックして上書きしたりできます。

上記の例では、ユーザーは既存のファイルを強調表示しました。
 「OK」をクリックすると、既存のファイルを置き換えることを確認するための確認ダイアログウィンドウが表示されます。 警告ダイアログにファイルの名前が表示されることに注意してください。 それは、 zenityにプロフェッショナルな外観を与える細部への一種の注意です。
 --confirm-overwriteオプションを使用していなかった場合、ファイルはサイレントに上書きされていたでしょう。 

 ファイルの名前は変数Responseに保存され、ターミナルウィンドウに出力されます。 

通知ダイアログウィンドウ
zenityを使用すると、スクリプトに滑らかな通知ダイアログウィンドウを含めるのが簡単になります。 ユーザーに情報、警告、エラーメッセージ、および質問を提供するために呼び出すことができるストックダイアログウィンドウがあります。
エラーメッセージダイアログウィンドウを作成するには、次のコマンドを使用します。
zenity --error --width 300 --text "アクセスが拒否されました。ファイルに書き込めません。"
使用している新しいオプションは次のとおりです。
-  –error :エラーダイアログウィンドウを使用することをzenityに通知します。
- –width :ウィンドウの初期幅を設定します。

指定した幅でエラーダイアログウィンドウが表示されます。 標準のGTKエラーアイコンを使用します。

情報ダイアログウィンドウを作成するには、次のコマンドを使用します。
zenity --info --width 300 --text "更新が完了しました。続行するには[OK]をクリックしてください。"
 使用している新しいオプションは--infoで、これはzenityに情報ダイアログウィンドウを作成するように指示します。 

質問ダイアログウィンドウを作成するには、次のコマンドを使用します。
zenity --question --width 300 --text "続行してもよろしいですか?"; エコー$?
 使用している新しいオプションは--questionです。これは、 zenityに質問ダイアログウィンドウを作成するように指示します。 

 $? は特別なパラメータです。 これは、最後に実行されたフォアグラウンドパイプラインからの戻り値を保持します。 一般的に、これは最後に閉じられたプロセスからの値です。 ゼロの値は「OK」を意味し、1つ以上の値は「キャンセル」を意味します。
 これは、任意のzenityダイアログウィンドウに適用できる一般的な手法です。 スクリプトでこの値を確認することにより、ダイアログウィンドウから返されたデータを処理するか無視するかを決定できます。 

「はい」をクリックしたので、戻りコードは「OK」を示すゼロです。

警告ダイアログウィンドウを作成するには、次のコマンドを使用します。
zenity --warning --title "Low Hard Drive Space" --width 300 --text "バックアップを保存するのに十分なハードドライブ容量がない可能性があります。"
 使用している新しいオプションは--warningです。これは、警告ダイアログウィンドウを作成するようにzenityに指示します。 

警告ダイアログウィンドウが表示されます。 質問ではないので、ボタンは1つだけです。

進行状況ダイアログウィンドウ
zenityの進行状況ダイアログウィンドウを使用して、スクリプトの完了にどれだけ近いかを示す進行状況バーを表示できます。

プログレスバーは、スクリプトからパイプされる値に従って進められます。 原理を示すために、次のコマンドを使用します。
(for i in $(seq 0 10 100); do echo $ i; sleep 1; done)

コマンドは次のように分類されます。
-  seqコマンドは、0から100までのシーケンスを10ステップでステップ実行します。
-  各ステップで、値は変数iに格納されます。 ターミナルウィンドウに印刷されます。
-  sleep 1コマンドのため、コマンドは1秒間一時停止します。
 これをzenityの進行状況ダイアログウィンドウで使用して、進行状況バーを示すことができます。 前のコマンドの出力をzenity:にパイプしていることに注意してください。
(for i in $(seq 0 10 100); do echo $ i; sleep 1; done)| zenity --progress --title "How-To Geek" --auto-close

使用している新しいオプションは次のとおりです。
-  –progress :進行状況ダイアログウィンドウを使用することをzenityに通知します。
- –auto-close :進行状況バーが100%に達したときにダイアログを閉じます。
進行状況ダイアログウィンドウが表示され、バーが100%に向かって進み、各ステップの間に1秒間一時停止します。

 値をzenityにパイプするという概念を使用して、進行状況ダイアログウィンドウをスクリプトに含めることができます。
このテキストをエディタに入力し、「progress.sh」として保存します。
 !/ bin / bash
関数work-list(){
echo "#最初の作業項目" 
エコー「25」
睡眠1
エコー「#2番目の作業項目」 
エコー「50」
睡眠1
エコー「#3番目の作業項目」 
エコー「75」
睡眠1
echo "#最後の作業項目" 
エコー「100」
睡眠1
}
ワークリスト| zenity --progress --title "How-To Geek" --auto-close
出口0スクリプトの内訳は次のとおりです。
-  スクリプトは、 work-listと呼ばれる関数を定義します。 これは、実際の作業を実行するためのコマンドと指示を配置する場所です。sleep 1コマンドのそれぞれを実際のコマンドに置き換えます。
-  zenityはecho "# ..."行を受け入れ、進行状況ダイアログウィンドウ内に表示します。 これらの行のテキストを変更して、ユーザーに有益なメッセージを渡すようにします。
-  echo "25"などの数字を含むechoラインもzenityによって受け入れられ、プログレスバーの値を設定します。
-  ワークリスト関数が呼び出され、 zenityにパイプされます。
次のコマンドを使用して、スクリプトを実行可能にします。
chmod + x progress.sh

次のコマンドを使用して、スクリプトを実行します。
./progress.sh

スクリプトが実行され、スクリプトの各フェーズが実行されるとテキストメッセージが変化します。 プログレスバーは100%に向かって段階的に移動します。

スケールダイアログウィンドウ
スケールダイアログウィンドウでは、スライダーを動かして数値を選択できます。 これは、彼女が高すぎる値または低すぎる値を入力できないことを意味します。
使用している新しいオプションは次のとおりです。
-  –scale :スケールダイアログウィンドウを使用することをzenityに通知します。
- –min-value :スケールの最小値を設定します。
- –max-value :スケールの最大値を設定します。
- –step :矢印キーを使用したときにスライダーが移動する量を設定します。 誰かがマウスを使用している場合、これはスライダーの動きには影響しません。
- –value :スライダーの初期値と位置を設定します。
これは私たちが使用しているコマンドです:
Response = $(zenity --scale --title "How-To Geek" --text "倍率を選択してください。"-min-value = 0 --max-value = 30 --step = 3 --value15); エコー$ Response

スライダーが15に設定された状態で、スライダーダイアログウィンドウが表示されます。

ユーザーはスライダーを動かして新しい値を選択できます。

 彼女が「OK」をクリックすると、値が変数Responseに転送され、ターミナルウィンドウに出力されます。 

入力ダイアログウィンドウ
入力ダイアログウィンドウでは、誰かがテキストを入力できます。
使用している新しいオプションは次のとおりです。
-  –entry :入力ダイアログウィンドウを使用することをzenityに通知します。
- –entry-text :テキスト入力フィールドに推奨値を入力する場合に使用できます。 空のフィールドを強制するために「」を使用しています。 これは厳密には必須ではありませんが、オプションを文書化する必要がありました。
完全なコマンドは次のようになります。
Response = $(zenity --entry --text "検索語を入力してください" --title "Howe-To Geek" --entry-text = ""); エコー$ Response

テキスト入力フィールドを含む単純なダイアログウィンドウが表示されます。

誰かがテキストを入力して編集できます。

「OK」をクリックすると、入力した値が変数Responseに割り当てられます。 エコーを使用して、ターミナルウィンドウに変数の値を出力します。

すべてを一緒に入れて
これらのテクニックを組み合わせて、機能的なスクリプトを作成しましょう。 スクリプトはハードウェア情報スキャンを実行し、スクロールするテキストウィンドウで結果をユーザーに表示します。 彼女はロングスキャンタイプまたはショートスキャンタイプを選択できます。
このスクリプトでは、3種類のダイアログウィンドウを使用します。そのうちの2つは新しいものです。
- 1つ目はリストダイアログウィンドウです。 それは誰かが選択をすることを可能にします。
- 2つ目は、進行状況ダイアログウィンドウで、ユーザーに何かが起こっていることを知らせます。ユーザーは待つ必要があります。
- 3つ目は、結果をユーザーに表示するテキスト情報ウィンドウです。
このテキストをエディターに入力し、「hardware-info.sh」として保存します。
 #!/ bin / bash
#このコンピューターのハードウェアリストを表示する
TempFile = $(mktemp)
ListType = `zenity --width = 400 --height = 275 --list --radiolist \
     --title 'ハードウェアスキャン' \
     --text 'スキャンタイプを選択します:' \
     -列 '選択' \
     --column 'スキャンタイプ' TRUE "短い" FALSE "長い" `
if [[$? -eq 1]]; それから
  #[キャンセル]を押すか、ダイアログウィンドウを閉じました 
  zenity --error --title = "Scan Declined" --width = 200 \
       --text = "ハードウェアスキャンがスキップされました"
  出口1
 
elif [$ ListType == "Short"]; それから
  #彼らは短いラジオボタンを選択しました 
  Flag = "-short"
 
それ以外
  #彼らは長いラジオボタンを選択しました 
  Flag = "" 
fi
#$ Flagで適切な値を持つハードウェア情報を検索する
hwinfo $ Flag | tee>(zenity --width = 200 --height = 100 \
     --title = "情報の収集" --progress \
     --pulsate --text = "ハードウェアをチェックしています..." \
     --auto-kill --auto-close)> $ {TempFile}
 
#スクロールウィンドウにハードウェア情報を表示する
zenity --width = 800 --height = 600 \
     -タイトル「ハードウェアの詳細」\
     --text-info --filename = "$ {TempFile}"
 
出口0次のコマンドを使用して実行可能にします。
chmod + xハードウェア-info.sh

このスクリプトは一時ファイルを作成し、ファイルの名前はTempFile変数に保持されます。
TempFile = $(mktemp)
 スクリプトは--listオプションを使用して、リストダイアログウィンドウと呼ばれるzenityダイアログウィンドウを作成します。 行末の「\」文字は、それらを折り返されている1つの長い行として扱うようにスクリプトに指示します。 プロセスは次のとおりです。
- ウィンドウの幅と高さを指定します。
-  リストダイアログウィンドウは列をサポートします。 --radiolistオプションを指定すると、最初の列がラジオボタンの列になります。
- ウィンドウのタイトルとテキストプロンプトを設定します。
- 最初の列のタイトルを「選択」に設定しました。 この列の内容はラジオボタンになります。
- 2列目のタイトルを「Select」に設定し、2列目の内容を提供します。 この列には、「Short」と「Long」の2つのテキストラベルがあります。 TRUEおよびFALSEインジケータは、ダイアログウィンドウが表示されたときにデフォルトで「Short」オプションが選択されていることを意味します。
-  このダイアログウィンドウの結果をListTypeという変数に保存しています。
 ListType = `zenity --width = 400 --height = 275 --list --radiolist \ 
     --title 'ハードウェアスキャン' \ 
     --text 'スキャンタイプを選択します:' \ 
     -列 '選択' \ 
     --column 'スキャンタイプ' TRUE "短い" FALSE "長い" ` ユーザーが「キャンセル」を押した場合、 ListType,の値を確認する必要はなく、単に終了することができます。 彼が「OK」を押した場合、彼が「短い」または「長い」ラジオボタンを選択したかどうかを確認する必要があります。
-  特別なパラメータ$?ユーザーが「OK」を押した場合はゼロになります。 彼が「キャンセル」を押すか、ウィンドウを閉じた場合、それは1に等しくなります。
-  1に等しい場合、スクリプトはエラー情報ダイアログウィンドウを表示して終了します。 彼が「OK」を押すと、 ListType変数の値のテストに進みます。
-  ListType変数が値「Short」を保持している場合、スクリプトはFlagという変数を「–short」に等しく設定します。
-  ListType変数が値「Short」を保持していない場合は、値「Long」を保持する必要があります。 スクリプトは、Flagという変数を「」と等しくなるように設定します。これは空の文字列です。
-  スクリプトは、次のセクションでFlag変数を使用します。
if [[$? -eq 1]]; それから #[キャンセル]を押すか、ダイアログウィンドウを閉じました zenity --error --title = "スキャンが拒否されました" --width = 200 \ --text = "ハードウェアスキャンがスキップされました" 出口1 elif [$ ListType == "Short"]; それから #彼らは短いラジオボタンを選択しました Flag = "-short" それ以外 #彼らは長いラジオボタンを選択しました Flag = "" fi
スクリプトがユーザーが必要とするスキャンのタイプを認識したので、ハードウェア情報スキャンを実行できます。
-  スクリプトはhwinfoコマンドを呼び出し、Flag変数の値を渡します。
-  Flagに「–short」が含まれている場合、hwinfoコマンドはショートスキャンを実行します。Flagの値が「」の場合、hwinfoには何も渡されず、デフォルトのロングスキャンが実行されます。
-  スクリプトは、出力をhwinfoからteeにパイプします。teeは出力をzenityとTempFileに送信します。
- スクリプトはプログレスバーダイアログウィンドウを作成します。 ダイアログウィンドウの幅と高さ、およびタイトルとプロンプトテキストを設定します。
-  スクリプトは、 hwinfoコマンドが生成する情報の量を事前に知ることができないため、プログレスバーを正しく100%に進めるように設定することはできません。--pulsateオプションを指定すると、進行状況ダイアログに移動インジケーターが表示されます。 これは、ユーザーに何かが起こっていることを通知し、ユーザーは待つ必要があります。
-  --auto-killオプションは、誰かが「キャンセル」をクリックするとスクリプトを終了します。
-  --auto-closeオプションを使用すると、監視しているプロセスが完了すると、進行状況ダイアログが自動的に閉じます。
 #$ Flagで適切な値を持つハードウェア情報を検索する
hwinfo $ Flag | tee>(zenity --width = 200 --height = 100 \
     --title = "情報の収集" --progress \
     --pulsate --text = "ハードウェアをチェックしています..." \
     --auto-kill --auto-close)> $ {TempFile} hwinfoスキャンが完了すると、スクリプトはzenityを呼び出して、-text --text-infoオプションを使用してテキスト情報ダイアログウィンドウを作成します。 テキスト情報ダイアログウィンドウには、 TempFileファイルの内容が表示されます。
- スクリプトは、ダイアログウィンドウとタイトルテキストの幅と高さを設定します。
-  --flenameオプションは、TempFIle変数に保持されているファイルの内容を読み取るために使用されます。
 #スクロールウィンドウにハードウェア情報を表示する 
zenity --width = 800 --height = 600 \ 
     -タイトル「ハードウェアの詳細」\ 
     --text-info --filename = "$ {TempFile}"ユーザーがテキスト情報ダイアログウィンドウを閉じると、スクリプトは終了します。
出口0
それを起動して見てみましょう。
./hardware-info.sh

リストボックスが表示されます。 デフォルトでは「Short」オプションが選択されています。
![[短い]オプションが選択された[リスト]ダイアログボックス。](/uploads/article/2914/q4l6tkaChWSsWZi1.png)
「長い」を選択し、「OK」をクリックしましょう。
![[長い]オプションが選択された[リスト]ダイアログボックス。](/uploads/article/2914/Nz3Kem5l4FyPC0iR.png)
進行状況ウィンドウがスライドインジケーターとともに表示されます。 ハードウェアスキャンが完了するまで画面に表示されたままになります。

ハードウェアスキャンが完了すると、スキャンの詳細を示すテキスト情報ダイアログウィンドウが表示されます。

「OK」をクリックします。
頑固なコマンドラインの騎手でさえ、いくつかのGUIダイアログウィンドウが控えめなBashスクリプトにプロフェッショナルなタッチを与えることができることを認めなければなりません。
