Создать индикатор выполнения в Bash
Как я могу создать индикатор выполнения с помощью bash?
Это мой сценарий:
#!/bin/bash
pass='number1 number12 number13 number14 number15 number16'
chk='number14'
for i in $pass ; do
if [ "$i" == "$chk" ]; then
echo ' Found ^_^'
else
echo 'loading 50%'
fi
done
Я хочу заменить echo 'loading 50%' с чем угодно, чтобы создать индикатор выполнения.
5 ответов
whiptail поставляется предустановленным в Ubuntu и многих других дистрибутивах и будет отображать полноэкранные (но все еще основанные на терминалах) элементы прогресса.
dialog это надмножество whiptail, так что этот пример будет одинаково хорошо работать с обоими. Он предоставляет более продвинутые элементы пользовательского интерфейса, поэтому он может пригодиться, если вы ищете взаимодействие с пользователем, такое как средства выбора файлов и формы, но его недостатком является то, что он не предустанавливается во многих системах.
for i in $(seq 1 100)
do
sleep 0.1
echo $i
done | whiptail --title 'Test script' --gauge 'Running...' 6 60 0
Обратите внимание, что вывод сценария интерпретируется в процентах, поэтому вам, возможно, придется соответствующим образом настроить вывод.
Whiptail и Dialog также позволяют вам изменять текст во время выполнения с помощью довольно загадочного синтаксиса:
phases=(
'Locating Jebediah Kerman...'
'Motivating Kerbals...'
'Treating Kessler Syndrome...'
'Recruiting Kerbals...'
)
for i in $(seq 1 100); do
sleep 0.1
if [ $i -eq 100 ]; then
echo -e "XXX\n100\nDone!\nXXX"
elif [ $(($i % 25)) -eq 0 ]; then
let "phase = $i / 25"
echo -e "XXX\n$i\n${phases[phase]}\nXXX"
else
echo $i
fi
done | whiptail --title 'Kerbal Space Program' --gauge "${phases[0]}" 6 60 0
pv показывает прогресс файла или потока, проходящего через него. Однако его нельзя (легко?) Использовать для отображения прогресса пользовательской операции, такой как цикл. Он разработан специально для потоков.
$ head -c 1G < /dev/urandom | pv -s 1G > /dev/null
277MB 0:00:16 [17.4MB/s] [========> ] 27% ETA 0:00:43
Некоторые примеры из реальной жизни, где pv пригодится:
# progress while importing a DB dump
pv mybigfile.sql | mysql -uroot -p dbname
# importing straight from a remote server
ssh user@server 'cat mybigfile.sql.gz' | pv | gzip -cd | mysql -uroot -p dbname
# taking a snapshot of a btrfs partition
btrfs send /snapshots/$date | pv | btrfs receive /mnt/backup/root
Я не знаю каких-либо команд, которые дают однострочные индикаторы выполнения в стиле pv или же wget, но есть много простых скриптов Bash/Perl/sed, которые добавят эту функциональность, как и другие здесь поделились.
Ты можешь использовать zenity создавать простые диалоговые окна GTK. Одним из доступных вариантов является диалоговое окно индикатора выполнения.
Вы создаете такое окно, используя zenity --progress, Чтобы сделать это полезным, вы должны указать больше информации, добавив некоторые из параметров ниже (выдержка из man zenity):
Progress options
--text=STRING
Set the dialog text
--percentage=INT
Set initial percentage
--auto-close
Close dialog when 100% has been reached
--auto-kill
Kill parent process if cancel button is pressed
--pulsate
Pulsate progress bar
--no-cancel
Hides the cancel button
Есть два режима:
пульсирующий: индикатор выполнения пульсирующий, он просто указывает на то, что что-то работает, но ничего не говорит о прогрессе. Вы делаете это, устанавливая
--pulsatingвариант.руководство: Вы должны передать текущий процент выполнения в
zenityстандартный ввод команды для обновления индикатора выполнения.
Пример для этого может выглядеть следующим образом. Обратите внимание, что предыдущие команды сгруппированы в подоболочку, поэтому весь вывод перенаправляется вzenityдиалог, а не только что из последней команды:(echo 10; sleep 2; echo 20; sleep 2; echo 50; sleep 2) | zenity --progress
Этот код сделает это, и не требует ничего (кроме bash, конечно). Это печатает # знаки, как вы просили в своем комментарии:
pass='number1 number12 number13 number14 number15 number16'
chk='number14'
passarr=($pass)
lenProgressBar=${#passarr[@]}
echo -n '['
i=0
while [ $i -lt $lenProgressBar ]; do
echo -n '-'
((i++))
done
echo -n ']'
i=0
while [ $i -lt $lenProgressBar ]; do
echo -e -n '\b'
((i++))
done
echo -e -n '\b'
for i in $pass ; do
if [ "$i" = "$chk" ]; then
echo -e '#\nFound ^_^'
break
else
echo -n '#'
fi
done
Однако, если вам есть что проверить, это просто заполнит ваш экран # приметы. Чтобы решить эту проблему, попробуйте этот код:
lenProgressBar=5
pass='number1 number12 number13 number14 number15 number16'
chk='number14'
passarr=($pass)
lenPass=${#passarr[@]}
if [ $lenProgressBar -gt $lenPass ]; then
lenProgressBar=lenPass
elif [ $lenProgressBar -lt 1 ]; then
lenProgressBar=1
fi
let "chksForEqualsPrint = $lenPass / $lenProgressBar"
echo -n '['
i=0
while [ $i -lt $lenProgressBar ]; do
echo -n '-'
((i++))
done
echo -n ']'
i=0
while [ $i -lt $lenProgressBar ]; do
echo -e -n '\b'
((i++))
done
echo -e -n '\b'
n=1
for i in $pass ; do
if [ "$i" = "$chk" ]; then
echo -e '\nFound ^_^'
break
else
if [ $n -eq $chksForEqualsPrint ]; then
echo -n '#'
n=1
else
((n++))
fi
fi
done
Поменяйте 5 в первой строке (lenProgressBar=5) на ту длину, которую вы хотите, чтобы ваш индикатор выполнения был. Это займет больше времени, чтобы напечатать # подписывайте с помощью индикаторов с меньшей длиной, чем с индикаторами с большей длиной, но не допускайте, чтобы длина индикатора выполнения превышала размер вашего экрана; это не будет работать хорошо, если вы делаете. (Это не позволит вам использовать индикатор выполнения больше, чем количество проверяемых элементов или меньше 1)
Вот еще один подход с использованием escape-кодов ANSI:
#!/bin/bash
pass='number1 number2 number 3 number4 number12 number13 number14 number15 number16'
chk='number15'
result="Not Found!"
echo
echo -n "Working... "
echo -ne "\033[1;32m\033[7m\033[?25l"
for i in $pass ; do
sleep .4s
if [ "$i" == "$chk" ]; then
result=" Found ^_^"
break
else
echo -n " "
fi
done
echo -ne "\r\033[0m\033[K\033[?25h"
echo $result
echo
Мне нужен был индикатор выполнения, который помещался бы во всплывающем сообщении () для представления уровня громкости телевизора. Недавно я писал музыкальный проигрыватель на питоне, и большую часть времени изображение с телевизора отключалось.
Пример вывода из терминала
Баш-скрипт
#!/bin/bash
# Show a progress bar at step number $1 (from 0 to 100)
function is_int() { test "$@" -eq "$@" 2> /dev/null; }
# Parameter 1 must be integer
if ! is_int "$1" ; then
echo "Not an integer: ${1}"
exit 1
fi
# Parameter 1 must be >= 0 and <= 100
if [ "$1" -ge 0 ] && [ "$1" -le 100 ] 2>/dev/null
then
:
else
echo bad volume: ${1}
exit 1
fi
# Main function designed for quickly copying to another program
Main () {
Bar="" # Progress Bar / Volume level
Len=25 # Length of Progress Bar / Volume level
Div=4 # Divisor into Volume for # of blocks
Fill="▒" # Fill up to $Len
Arr=( "▉" "▎" "▌" "▊" ) # UTF-8 left blocks: 7/8, 1/4, 1/2, 3/4
FullBlock=$((${1} / Div)) # Number of full blocks
PartBlock=$((${1} % Div)) # Size of partial block (array index)
while [[ $FullBlock -gt 0 ]]; do
Bar="$Bar${Arr[0]}" # Add 1 full block into Progress Bar
(( FullBlock-- )) # Decrement full blocks counter
done
# If remainder zero no partial block, else append character from array
if [[ $PartBlock -gt 0 ]]; then
Bar="$Bar${Arr[$PartBlock]}"
fi
while [[ "${#Bar}" -lt "$Len" ]]; do
Bar="$Bar$Fill" # Pad Progress Bar with fill character
done
echo Volume: "$1 $Bar"
exit 0 # Remove this line when copying into program
} # Main
Main "$@"
Тестовый bash-скрипт
Используйте этот скрипт для проверки индикатора выполнения в терминале.
#!/bin/bash
# test_progress_bar3
Main () {
tput civis # Turn off cursor
for ((i=0; i<=100; i++)); do
CurrLevel=$(./progress_bar3 "$i") # Generate progress bar 0 to 100
echo -ne "$CurrLevel"\\r # Reprint overtop same line
sleep .04
done
echo -e \\n # Advance line to keep last progress
echo "$0 Done"
tput cnorm # Turn cursor back on
} # Main
Main "$@"
TL;DR
В этом разделе подробно описано, как используется для быстрого спама всплывающих сообщений на рабочем столе. Это необходимо, поскольку уровень громкости может меняться много раз в секунду, а поведение пузырькового сообщения по умолчанию заключается в том, что сообщение остается на рабочем столе в течение многих секунд.
Пример всплывающего всплывающего сообщения
Bash-код всплывающего всплывающего сообщения
Из скрипта выше функция была скопирована в новый функционал с именем
VolumeBarв существующем сценарии bash, называемом
tvpowered.
exit 0команда в скопированном
mainфункция была удалена.
Вот как это вызвать и сообщить команде Ubuntu, что мы будем рассылать спам всплывающим сообщением:
VolumeBar $CurrVolume
# Ask Ubuntu: https://askubuntu.com/a/871207/307523
notify-send --urgency=critical "tvpowered" \
-h string:x-canonical-private-synchronous:volume \
--icon=/usr/share/icons/gnome/48x48/devices/audio-speakers.png \
"Volume: $CurrVolume $Bar"
Это новая строка, которая говорит
notify-sendчтобы немедленно заменить последний всплывающий пузырь:
-h string:x-canonical-private-synchronous:volume \
группирует всплывающие сообщения вместе, и новые сообщения в этой группе немедленно заменяют предыдущие. Вы можете использовать
anythingвместо
volume.


