Mostra Spinner in attesa che il processo finisca


13

Come posso mostrare il filatore fino a quando la riga di comando non termina è lavoro? In altre parole, se sto eseguendo uno script e voglio mostrare lo spinner mentre lo script è in esecuzione e lo spinner scompare al termine dello script, è lavoro.

Bellow è un codice spinner comune:

i=1
sp="/-\|"
echo -n ' '
while true
do
printf "\b${sp:i++%${#sp}:1}"
done

Come posso collegare il precedente codice spinner a un comando per fargli mostrare lo spinner mentre il comando è in esecuzione e lo spinner scompare quando il comando termina è lavoro? Se includo il comando all'interno del loop, esso verrà eseguito in loop con lo spinner, quindi qual è la soluzione in questo caso?

bash 

Risposte:


21

Fai in modo che il tuo whileloop guardi per uscire dal tuo vero comando. Assumerò un ambiente Linux con voci / proc per ciascun PID, ma potresti tagliarlo in altri modi:

#!/bin/bash
# your real command here, instead of sleep
sleep 7 &
PID=$!
i=1
sp="/-\|"
echo -n ' '
while [ -d /proc/$PID ]
do
  printf "\b${sp:i++%${#sp}:1}"
done

9
Questo è un circuito affollato che divorerà le risorse della CPU. Suggerirei di avere un ritardo di qualche tipo nel tuo ciclo while.
ACase

16

Questo script di shell dovrebbe fare quello che stai cercando:

#!/usr/bin/env bash

show_spinner()
{
  local -r pid="${1}"
  local -r delay='0.75'
  local spinstr='\|/-'
  local temp
  while ps a | awk '{print $1}' | grep -q "${pid}"; do
    temp="${spinstr#?}"
    printf " [%c]  " "${spinstr}"
    spinstr=${temp}${spinstr%"${temp}"}
    sleep "${delay}"
    printf "\b\b\b\b\b\b"
  done
  printf "    \b\b\b\b"
}

("$@") &
show_spinner "$!"

Supponendo che tu memorizzi lo script della shell in un file chiamato spinner, puoi invocarlo in questo modo per visualizzare uno spinner mentre il comando sleep 10è in esecuzione:

$ spinner sleep 10


Ciò presuppone che venga chiamato lo script della shell spinner, quindi no. Penso che l'esempio sia giusto, supponendo che tu chiami lo script spinner.
jsears,

3

Ecco un altro filatore di fantasia che puoi usare in questo modo:

spinner ping google.com
echo "ping exited with exit code $?"

spinner sleep 10
echo "sleep exited with exit code $?"

Ha 12 temi e ne sceglie uno a caso.

#!/bin/bash
# Shows a spinner while another command is running. Randomly picks one of 12 spinner styles.
# @args command to run (with any parameters) while showing a spinner. 
#       E.g. ‹spinner sleep 10›

function shutdown() {
  tput cnorm # reset cursor
}
trap shutdown EXIT

function cursorBack() {
  echo -en "\033[$1D"
}

function spinner() {
  # make sure we use non-unicode character type locale 
  # (that way it works for any locale as long as the font supports the characters)
  local LC_CTYPE=C

  local pid=$1 # Process Id of the previous running command

  case $(($RANDOM % 12)) in
  0)
    local spin='⠁⠂⠄⡀⢀⠠⠐⠈'
    local charwidth=3
    ;;
  1)
    local spin='-\|/'
    local charwidth=1
    ;;
  2)
    local spin="▁▂▃▄▅▆▇█▇▆▅▄▃▂▁"
    local charwidth=3
    ;;
  3)
    local spin="▉▊▋▌▍▎▏▎▍▌▋▊▉"
    local charwidth=3
    ;;
  4)
    local spin='←↖↑↗→↘↓↙'
    local charwidth=3
    ;;
  5)
    local spin='▖▘▝▗'
    local charwidth=3
    ;;
  6)
    local spin='┤┘┴└├┌┬┐'
    local charwidth=3
    ;;
  7)
    local spin='◢◣◤◥'
    local charwidth=3
    ;;
  8)
    local spin='◰◳◲◱'
    local charwidth=3
    ;;
  9)
    local spin='◴◷◶◵'
    local charwidth=3
    ;;
  10)
    local spin='◐◓◑◒'
    local charwidth=3
    ;;
  11)
    local spin='⣾⣽⣻⢿⡿⣟⣯⣷'
    local charwidth=3
    ;;
  esac

  local i=0
  tput civis # cursor invisible
  while kill -0 $pid 2>/dev/null; do
    local i=$(((i + $charwidth) % ${#spin}))
    printf "%s" "${spin:$i:$charwidth}"

    cursorBack 1
    sleep .1
  done
  tput cnorm
  wait $pid # capture exit code
  return $?
}

("$@") &

spinner $!

2

Se si desidera uno spinner con il minimo comune denominatore che funziona con / bin / sh e non si basa sulla sostituzione estesa del parametro bash, dovrebbe funzionare:

#!/bin/sh

# The command you are waiting on goes between the ( ) here
# The example below returns a non zero return code

(sleep 20 ; /bin/false) &

pid=$! ; i=0
while ps -a | awk '{print $1}' | grep -q "${pid}"
do
    c=`expr ${i} % 4`
    case ${c} in
       0) echo "/\c" ;;
       1) echo "-\c" ;;
       2) echo "\\ \b\c" ;;
       3) echo "|\c" ;;
    esac
    i=`expr ${i} + 1`
    # change the speed of the spinner by altering the 1 below
    sleep 1
    echo "\b\c"
done

# Collect the return code from the background process

wait ${pid}
ret=$?

# You can report on any errors due to a non zero return code here

exit ${ret}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.