Hiển thị Spinner trong khi chờ quá trình hoàn tất


13

Làm thế nào tôi có thể hiển thị spinner cho đến khi dòng lệnh kết thúc nó là công việc? Nói cách khác, nếu tôi đang chạy một kịch bản và tôi muốn hiển thị spinner trong khi script này đang chạy và spinner biến mất khi script hoàn thành thì đó là công việc.

Bellow là một mã spinner phổ biến:

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

Làm thế nào tôi có thể liên kết mã spinner trước đó với một lệnh để cho nó hiển thị spinner trong khi lệnh đang chạy và spinner biến mất khi lệnh kết thúc nó là công việc? Nếu tôi bao gồm lệnh bên trong vòng lặp, nó sẽ lặp với spinner, vậy giải pháp trong trường hợp này là gì?

bash 

Câu trả lời:


21

whilevòng lặp của bạn cho lệnh thực sự của bạn để thoát. Tôi sẽ giả sử một môi trường Linux có / mục nhập cho mỗi PID, nhưng bạn có thể cắt nó theo các cách khác:

#!/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
Đây là một vòng lặp bận rộn sẽ ăn hết tài nguyên cpu. Tôi khuyên bạn nên trì hoãn một số loại trong vòng lặp while của bạn.
ACase

15

Kịch bản shell này sẽ làm những gì bạn đang tìm kiếm:

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

Giả sử bạn lưu trữ tập lệnh shell trong một tệp có tên spinner, bạn có thể gọi nó như thế này để hiển thị một công cụ quay vòng trong khi lệnh sleep 10đang chạy:

$ spinner sleep 10


Điều này giả sử kịch bản shell được gọi spinner, vì vậy không. Tôi nghĩ ví dụ này là đúng, giả sử bạn đặt tên cho kịch bản spinner.
jsears

3

Đây là một spinner ưa thích khác mà bạn có thể sử dụng như thế này:

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

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

Nó có 12 chủ đề và chọn một chủ đề ngẫu nhiên.

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

Nếu bạn muốn một công cụ tạo mẫu số chung thấp nhất hoạt động với / bin / sh và không phụ thuộc vào thay thế tham số bash mở rộng thì điều này sẽ hoạt động:

#!/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}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.