Bash模板使用zenity(或yad)在文件或数据库中插入/编辑/删除记录

我正在寻找一个使用zenityyad维护记录列表的bash模板。 模板可以是带有打印选项的购物清单,也可以是监控ping时间的服务器列表。 在任何一种情况下,我都想采用该代码并根据我的需要采用它。

这是一个示例对话框模型:

websync 1

该对话框允许选择记录并单击以下按钮:

  • Insert before (在选定记录Insert before插入)。 安装新的输入表单以输入字段。
  • Edit (编辑所选记录)。 安装与“之前插入”相同的格式,但显示现有值除外。
  • Delete (删除所选记录)。 显示现有记录的内容并请求确认。
  • Run – 运行一个冗长的更新过程,使用“MatcheOK / Different / Error”更新状态列。 系统会提示用户对所选记录或所有记录运行更新。 处理所有记录时显示进度显示栏。
  • Cancel ALL – 不保存任何更改并退出bash脚本。 单击XEscape或关闭窗口将执行相同的操作。 如果任何记录已更改,则请求确认。
  • Save – 将更改保存到磁盘并退出bash脚本。

注意:看起来zenity只允许重新标记“确定”和“取消”按钮。 无法在zenity中定义新按钮。 因此,默认安装在Ubuntu中并且基于zenity的yad( Y et A nother D ialog)是要走的路。 然而,zenity仍然存在于问题中,因为基于它的脚本可以很容易地转换为yad。

我用谷歌搜索了现有的例子,这些是最接近的,但仍然远远不能令人满意:

  • 从zenity更新文本文件

  • 使用SQL中的列表填充zenity

  • 使用脚本文件中的zenity在SQL中插入/查看数据

  • 可滚动字段的示例太长而无法放入窗口中

  • 使用yad(Yet Another Dialog)一个Zenity的叉子,用于多个按钮

  • Source Forge的关闭电源/重启/暂停/注销的示例

注意:我不是在寻找一个完整的解决方案,但是可以适应这个项目。 虽然此项目使用平面文本文件,但可以调整使用SQL,ISAM或RDMS的现有脚本。 唯一的要求是用bash编写而不是python,perl或C等。

任何人都可以指出使用zenity(或yad)插入/编辑/删除记录的现有bash脚本吗?

YAD(又一个对话)是最好的方法

YAD是Zenity的一个分支,提供对按钮,列表和GTK界面的高级控制。 例如,在这个答案中输入文件名时,YAD很容易为我们提供常规的GUI系统界面:

websync文件输入

示例主对话框窗口

主窗口隐藏了记录编号列,您可以显示该列以进行调试:

websync主要

示例插入/编辑窗口

同一窗口用于在现有记录之前插入记录或编辑现有记录:

websync编辑

注意“文件名”字段。 输入时,将出现第一部分中的文件选择对话框。

bash代码

下面是使用示例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: $ij: $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 ' \ Click column heading to sort.\ Select record before clicking: Insert / Edit / Delete' \ --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 'Click OK to confirm delete.' \ --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候选者。 我期待着对此的评论,因为我真的不确定最好的地方。

当然,我总是期待一般性的评论和建设性的批评:)