แสดงสปินเนอร์ขณะที่รอให้กระบวนการเสร็จสิ้น


13

ฉันจะแสดงสปินเนอร์จนจบบรรทัดคำสั่งได้หรือไม่ กล่าวอีกนัยหนึ่งถ้าฉันใช้งานสคริปต์และฉันต้องการที่จะแสดงสปินเนอร์ในขณะที่สคริปต์นี้ทำงานและสปินเนอร์หายไปเมื่อสคริปต์เสร็จมันเป็นงาน

ร้องเป็นรหัสปั่นด้ายที่พบบ่อย:

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

ฉันจะเชื่อมโยงรหัสสปินเนอร์ก่อนหน้าเข้ากับคำสั่งเพื่อให้มันแสดงสปินเนอร์ได้ในขณะที่คำสั่งนั้นทำงานอยู่และสปินเนอร์จะหายไปเมื่อคำสั่งทำงานเสร็จ ถ้าฉันรวมคำสั่งในลูปมันจะวนซ้ำกับสปินเนอร์ดังนั้นวิธีแก้ปัญหาในกรณีนี้คืออะไร?

bash 

คำตอบ:


22

ให้whileวงดูเพื่อให้คำสั่งจริงของคุณออก ฉันจะถือว่าสภาพแวดล้อม Linux ที่มี / proc รายการสำหรับแต่ละ PID แต่คุณสามารถเชือดมันด้วยวิธีอื่น ๆ :

#!/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
นี่คือการวนรอบไม่ว่างที่จะกินทรัพยากร cpu ฉันขอแนะนำให้มีความล่าช้าบางอย่างในขณะที่คุณวนรอบ
กรณี

16

เชลล์สคริปต์นี้ควรทำสิ่งที่คุณต้องการ:

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

สมมติว่าคุณเก็บเชลล์สคริปต์ไว้ในไฟล์ชื่อspinnerคุณสามารถเรียกใช้มันเพื่อแสดงสปินเนอร์ขณะที่คำสั่งsleep 10กำลังทำงานอยู่:

$ spinner sleep 10


สิ่งนี้ถือว่าเชลล์สคริปต์ถูกเรียกใช้spinnerดังนั้นไม่ใช่ spinnerผมคิดว่าตัวอย่างที่ถูกต้องสมมติว่าคุณชื่อสคริปต์
jsears

3

นี่คืออีกหนึ่งปินเนอร์แฟนซีที่คุณสามารถใช้เช่นนี้:

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

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

มันมี 12 ธีมและเลือกหนึ่งแบบสุ่ม

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

หากคุณต้องการสปินเนอร์ตัวหารร่วมที่ต่ำที่สุดที่ทำงานกับ / bin / sh และไม่พึ่งพาการทดแทนพารามิเตอร์ bash แบบขยายสิ่งนี้ควรใช้งาน:

#!/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}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.