web-dev-qa-db-ja.com

Zenity(またはYAD)を使用してファイルまたはデータベースのレコードを挿入、編集、削除するためのBashテンプレート

私はzenityまたはyadを使用するbashテンプレートを探していますレコードのリストを維持します。テンプレートは、印刷オプション付きのショッピングチェックリストにすることも、ping時間を監視するサーバーのリストにすることもできます。どちらの場合でも、そのコードを取得して、自分のニーズに合わせて採用したいと思います。

次に、ダイアログボックスのサンプルモックアップを示します。

websync 1

このダイアログボックスでは、レコードを選択し、次のボタンをクリックできます。

  • Insert before(選択したレコードの前に挿入)。フィールドを入力するための新しい入力フォームがマウントされます。
  • Edit(選択したレコードを編集)。既存の値が表示されることを除き、「前に挿入」と同じフォームをマウントします。
  • Delete(選択したレコードを削除)。既存のレコードの内容が表示され、確認が要求されます。
  • Run-「MatcheOK/Different/Error」でステータス列を更新する長い更新プロセスを実行します。ユーザーは、選択したレコードまたはすべてのレコードで更新を実行するように求められます。すべてのレコードが処理されたときに表示される進行状況表示バー。
  • Cancel ALL-変更を保存せずにbashスクリプトを終了します。押す Escape またはXをクリックしてウィンドウを閉じると、同じアクションが実行されます。レコードが変更された場合、確認が要求されます。
  • Save-変更をディスクに保存し、bashスクリプトを終了します。

注:zenityでは、「OK」ボタンと「Cancel」ボタンのラベルのみを変更できます。新しいボタンを完全に定義することはできません。そのようなyad(YetAnotherDialog)これはUbuntuにデフォルトでインストールされ、zenityに基づいて実行する方法です。ただし、Zenityに基づくスクリプトは簡単にyadに変換できるため、Zenityは疑問のままです。

既存の例をグーグルで検索しましたが、これらは最も近いものですが、まだ満足できるものではありません。

注:完全なソリューションを探しているのではなく、このプロジェクトに適応できる近いものを探しています。このプロジェクトはフラットテキストファイルを使用しますが、SQL、ISAMまたはRDMSを使用する既存のスクリプトを適合させることができます。唯一の必須事項は、Python、Perl、Cなどではなく、bashで記述されていることです。

Zenity(またはyad)を使用してレコードを挿入/編集/削除する既存のbashスクリプトを指摘できますか?

4

YAD(Yet Another Dialog)は最良の方法です

YADはZenityのフォークであり、ボタン、リスト、GTKインターフェイスを高度に制御します。たとえば、この回答にファイル名を入力すると、YADは通常のGUIシステムインターフェイスを簡単に提供します。

websync file input

メインダイアログウィンドウのサンプル

メインウィンドウは、デバッグ目的で表示できるレコード番号列を非表示にします。

websync main

サンプルの挿入/編集ウィンドウ

同じウィンドウを使用して、既存のレコードの前にレコードを挿入したり、既存のレコードを編集したりします。

websync edit

「ファイル名」フィールドに注意してください。入力すると、最初のセクションのファイル選択ダイアログボックスが表示されます。

バッシュコード

サンプルYADのレコードの挿入/編集/削除テンプレートを作成するためのbashコードは次のとおりです。ファイルを読み込んで「実行」コマンドの処理ロジックを追加するには、追加のコーディングが必要です。スペースが埋め込まれたファイル名をサポートするには、おそらく追加のコーディングが必要ですが、まだテストされていません。

#!/bin/bash

# NAME: websync
# PATH: $HOME/bin
# DESC: Provide list of files and corresponding website addresses.

# DATE: Mar 25, 2017.

# NOTE: Uses yad which is fork of zenity which is GUI fork of dialog.

# TODO: Add local file date modified. Add Answer last revision date.
#       Add question title.
#       Add file Word count, or size, or ignore as irrelevant?
#   Add answer Word count if file Word count is displayed.
#       Add answer up votes.
#   Scan directory to add all files. ("Populate" button)
#   Initialize $ListArr[@] < /home/$USER/bin/.websync
#   Use "|" as ListArr delimeter or (double quotes?) for file names with spaces

# Must have the yad package.
command -v yad >/dev/null 2>&1 || { echo >&2 "yad package required but it is not installed.  Aborting."; exit 99; }

# Must have the zenity package.
command -v zenity >/dev/null 2>&1 || { echo >&2 "yad package required but it is not installed.  Aborting."; exit 99; }

RenumberListArr () {
# This is called after inserting or deleting records.
# Record numbers may not be sequential because user can sort on any column
# Record nubmers must be unique as they are used to find the correct record in ListArr array.
# Matching on "file name" or any other field is impossible because there may be duplicate names.

# Define variables for easy reading and fewer code line changes when expanding
RecArrCnt=5
ListArrCnt=${#ListArr[@]}

i=1 # First element (0) is "false", followed by record number element (1)
j=1 # Record numbers start at 1

while [ $i -lt $ListArrCnt ] ; do
    ListArr[$i]=$j
    j=$(($j + 1))
    i=$(($i + $RecArrCnt))
# echo "Renumber i: $i j: $j"
done

}

OLDIFS="$IFS"
IFS="|"
ListArr=()

# TODO: Replace this section with IFS=' ' read -ra CfgArr < /home/$USER/bin/.websync

ListArr=("${ListArr[@]}" false "1" "/usr/local/bin/display-auto-brightness" "Different")
Modified=$(stat "/usr/local/bin/display-auto-brightness" | grep "Modify:"| cut -f2 -d" ")
echo "Modified: $Modified" # File modified date is a future list array new field
ListArr=("${ListArr[@]}" "http://askubuntu.com/questions/894460/automatically-adjust-display-brightness-based-on-sunrise-and-sunset/894470#894470")
ListArr=("${ListArr[@]}" false "2" "/usr/local/bin/Sun-hours" "Matches")
ListArr=("${ListArr[@]}" "http://askubuntu.com/questions/894460/automatically-adjust-display-brightness-based-on-sunrise-and-sunset/894470#894470")
ListArr=("${ListArr[@]}" false "3" "/etc/cron.daily/Sun-hours" "Matches")
ListArr=("${ListArr[@]}" "http://askubuntu.com/questions/894460/automatically-adjust-display-brightness-based-on-sunrise-and-sunset/894470#894470")
ListArr=("${ListArr[@]}" false "4" "/home/rick/.conkyrc" "Matches")
ListArr=("${ListArr[@]}" "http://askubuntu.com/questions/894460/automatically-adjust-display-brightness-based-on-sunrise-and-sunset/894470#894470")
ListArr=("${ListArr[@]}" false "5" "/usr/local/bin/auto-brightness-config" "Matches")
ListArr=("${ListArr[@]}" "http://askubuntu.com/questions/894460/automatically-adjust-display-brightness-based-on-sunrise-and-sunset/894470#894470")
ListArr=("${ListArr[@]}" false "6" "/etc/cron.d/display-auto-brightness" "Matches")
ListArr=("${ListArr[@]}" "http://askubuntu.com/questions/894460/automatically-adjust-display-brightness-based-on-sunrise-and-sunset/894470#894470")
ListArr=("${ListArr[@]}" false "7" "/home/rick/bin/indicator-sysmonitor-display" "Different")
ListArr=("${ListArr[@]}" "http://askubuntu.com/questions/882419/can-bash-display-in-systray-as-application-indicator/882420#882420")

TransCount=0 # Number of Inserts, Edits and Deletes

# Read Only Status column: Recalc, Different, Matches, Bad File, No Address, Bad Address
# Debugging: --hide-column=2 hides Read Only record number column for normal operation

while true ; do

# adjust width & height below for your screen 900x600 default for 1920x1080 HD screen
# also adjust font="14" below if blue title text is too small or too large
Record=(`yad \
    --title "websync - Compare local scripts to those published on internet." --list \
        --text '<span foreground="blue" font="14"> \
        Click column heading to sort.\
        Select record before clicking: Insert / Edit / Delete</span>' \
        --width=1200 --height=600 --center --radiolist -separator="$IFS" \
        --button="Insert before":10 --button="Edit":20 --button="Delete":30 --button="Run":40 \
        --button="Cancel ALL":50 --button="Save":60 --search-column=3 \
        --column "Select" --column "Record number" --hide-column=2 --column "File Name" \
        --column "Status" --column " Website Address" \
        "${ListArr[@]}"`)
Action=$?

RecSelected=false
RecArr=()
i=0

# Button values 1 and 3 don't work for returning selected record for some reason???
# Button values 11, 13 and 15 don't work either. 12, 14 and 16 work. 
# Therefore use Button values (10, 20, 30...) for readability.
for Field in "${Record[@]}" ; do
    RecSelected=true
    RecArr[i++]=$Field
done

# Define variables for easy reading and fewer code line changes when expanding
RecArrCnt=5
ListArrCnt=${#ListArr[@]}

# Error checking
if [[ $Action == 10 ]] || [[ $Action == 20 ]] || [[ $Action == 30 ]] ; then
    if [[ $RecSelected == false ]] ; then
    zenity --error --text 'You must select a record before clicking: Insert / Edit / Delete.'
    continue
    fi
fi

# Insert before || or Edit ?
if [[ $Action == 10 ]] || [[ $Action == 20 ]] ; then

    RecArr[3]="Recalc"
    # --text="Set fields and click OK to update" 
    # Note if there is a space at end of line, next line generates invalid command error from yad
    NewRecArr=(`yad --width=900 --height=300 --title="Link file to Website Address" \
        --form --center \
        --field="File name":FL --field="Status":RO \
        --field="Website Address":TXT \
        ${RecArr[2]} ${RecArr[3]} ${RecArr[4]}`)
    ret=$?

    # Cancel =252, OK = 0
    # OK & Insert operation?
    if [[ $ret == 0 ]] && [[ $Action == 10 ]]; then
        # Create new list entry and renumber
    ((TransCount++)) # Update number of changes
        let i=1      # Base 0 array, record number is second field

    while [ $i -lt $ListArrCnt ] ; do
        if [ ${ListArr[$i]} -eq ${RecArr[1]} ]; then
        # We have matching record number to insert before
            NewArr+=( false )
            NewArr+=( "${ListArr[$i]}" )
            NewArr+=( "${NewRecArr[0]}" )
            NewArr+=( "${NewRecArr[1]}" )
            NewArr+=( "${NewRecArr[2]}" )
        fi
        let j=$(( $i-1 ))
        let k=$(( $j+$RecArrCnt ))
        while [ $j -lt $k ] ; do
            NewArr+=( "${ListArr[$j]}" )
        j=$(($j + 1))
        done
        let i=$(($i + $RecArrCnt)) # Next list array entry to copy
    done
    ListArr=("${NewArr[@]}")
    unset NewArr
    RenumberListArr

    # OK & Edit operation?
    Elif [[ $ret == 0 ]] && [[ $Action == 20 ]]; then
        # Update array entry
    ((TransCount++))
        let i=1
    while [ $i -lt $ListArrCnt ] ; do
        if [ ${ListArr[$i]} -eq ${RecArr[1]} ]; then
        # We have matching record number
        ListArr[++i]="${NewRecArr[0]}"
        ListArr[++i]="New"
        ListArr[++i]="${NewRecArr[2]}"
        let i=$(($ListArrCnt + 1)) # force exit from while loop
        else
        let i=$(($i + $RecArrCnt)) # Check next entry
        fi
    done
    fi

# Delete record?
Elif [[ $Action == 30 ]] ; then
    # --text="click OK to confirm delete" 
    # Note if there is a space at end of a script line, the next line generates 
    # "invalid command error from yad
    yad --width=900 --height=300 --title="Do you really want to delete this record?" \
        --text '<span foreground="blue" font="14">Click OK to confirm delete.</span>' \
        --form --center \
        --field="File name":RO --field="Status":RO \
        --field="Website Address":RO \
        ${RecArr[2]} ${RecArr[3]} ${RecArr[4]}
    ret=$?

    # Cancel =252, OK = 0
    if [[ $ret == 0 ]] ; then
        # Delete record from list array and renumber
    ((TransCount++))
        let i=1
    while [ $i -lt $ListArrCnt ] ; do
        if [ ${ListArr[$i]} -eq ${RecArr[1]} ]; then
        # We have matching record number
        j=$(($i - 1))
        k=$(($j + $RecArrCnt))
        while [ $j -lt $k ] ; do
            unset 'ListArr[$j]'
            j=$(($j + 1))
        done
        for i in "${!ListArr[@]}"; do
                NewArr+=( "${ListArr[$i]}" )
        done
        ListArr=("${NewArr[@]}")
        unset NewArr
        let i=$(($ListArrCnt + 1)) # force exit from while loop
        else
        let i=$(($i + $RecArrCnt)) # Check next entry
        fi
    done
    RenumberListArr
    else
        continue # cancel changes.
    fi

# Run update process?
Elif [[ $Action == 40 ]] ; then
    continue # TODO: Run

# Cancel all changes?
Elif [[ $Action == 50 ]] || [[ $Action == 252 ]] ; then
    # Cancel ALL || or X the window or Escape
    if [[ $TransCount -gt 0 ]] ; then
    zenity --question --text "You have made $TransCount change(s). Do you really want to cancel?"
    rc=$? 
    if [[ $rc -eq 0 ]] ; then
        exit
    fi
    else
    exit
    fi

# Save changes?
Elif [[ $Action == 60 ]] ; then
    # Save
    echo ${ListArr[@]} > ~/bin/.websync
    exit
else
    zenity --error --text "~/bin/websync - Unknown button return code: $Action"
    exit
fi

done # End of while loop

IFS="$OLDIFS"

exit

概要

bashyadを使用して、他の人が独自のレコード管理システムを使用する時間を大幅に節約できることを願っています。もちろんPythonまたはCを使用して、より多くの防弾およびおそらくより高速なメソッドを実行できますが、それはおそらくより多くのコード行とより高い学習曲線を犠牲にします。

結局のところ、このプロジェクトは、bashとbashのみの環境で達成できることについてもっと知りたい人を対象としています。

たぶん、AskUbuntuはこれを投稿するのに間違ったフォーラムであり、Stack OverflowまたはUnix&LinuxフォーラムがStack Exchangeの候補者になるかもしれません。私は本当に最高の場所がわからないので、それに関するコメントを楽しみにしています。

もちろん、一般的なコメントと建設的な批判も常に楽しみにしています:)

2