Zeigen Sie Spinner an, während Sie darauf warten, dass ein Vorgang abgeschlossen ist

13

Wie kann ich den Spinner zeigen, bis die Befehlszeile fertig ist? Mit anderen Worten: Wenn ich ein Skript ausführe und den Spinner anzeigen möchte, während dieses Skript ausgeführt wird, und der Spinner verschwindet, wenn das Skript beendet ist, ist es ein Job.

Bellow ist ein gängiger Spinner-Code:

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

Wie kann ich den vorherigen Spinner-Code mit einem Befehl verknüpfen, damit er den Spinner anzeigt, während der Befehl ausgeführt wird und der Spinner verschwindet, wenn der Befehl beendet ist? Wenn ich den Befehl in die Schleife einbinde, wird er mit dem Spinner wiederholt. Was ist in diesem Fall die Lösung?


quelle

Antworten:

21

Lassen Sie Ihre whileSchleife auf Ihren eigentlichen Befehl zum Beenden achten. Ich gehe von einer Linux-Umgebung aus, die / proc-Einträge für jede PID enthält, aber Sie können es auch auf andere Weise aufteilen:

#!/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
Jeff Schaller
quelle
9
Dies ist eine belebte Schleife, die CPU-Ressourcen verbraucht. Ich würde vorschlagen, eine Verzögerung in Ihrer while-Schleife zu haben.
ACase
15

Dieses Shell-Skript sollte das tun, wonach Sie suchen:

#!/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 "$!"

Angenommen, Sie speichern das Shell-Skript in einer Datei mit dem Namen spinner, können Sie es wie sleep 10folgt aufrufen, um einen Spinner anzuzeigen, während der Befehl ausgeführt wird:

$ spinner sleep 10
jsears
quelle
Dies setzt voraus, dass das Shell-Skript aufgerufen wird spinner, also nein. Ich denke, das Beispiel ist richtig, vorausgesetzt, Sie nennen das Skript spinner.
jsears
2

Wenn Sie einen Spinner mit dem kleinsten gemeinsamen Nenner möchten, der mit / bin / sh funktioniert und sich nicht auf die erweiterte Bash-Parameterersetzung verlässt, sollte dies funktionieren:

#!/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}
Rob Bartlett
quelle
2

Hier ist ein weiterer ausgefallener Spinner, den Sie so verwenden können:

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

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

Es hat 12 Themen und wählt eines zufällig aus.

#!/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 $!
Jonas Eberle
quelle