쉘 스크립트에 진행률 표시 줄을 추가하는 방법?


413

bash 또는 * NIX의 다른 쉘에서 스크립팅 할 때 몇 초 이상 걸리는 명령을 실행하는 동안 진행 표시 줄이 필요합니다.

예를 들어, 큰 파일을 복사하여 큰 tar 파일을 엽니 다.

쉘 스크립트에 진행률 표시 줄을 추가하는 방법은 무엇입니까?


제어 로직의 예 는 stackoverflow.com/questions/12498304/… 도 참조하십시오 (작업을 백그라운드로하고 완료 될 때까지 무언가를 수행하십시오).
tripleee

1
스크립팅시 유용하게 사용되는 일련의 요구 사항이 있습니다. 로깅, 진행률, 색상, 멋진 출력 등을 표시합니다. 나는 항상 간단한 스크립팅 프레임 워크가 필요하다고 느꼈습니다. 마침내 찾을 수 없기 때문에 구현하기로 결정했습니다. 도움이 될 수 있습니다. 그것은 순수한 bash에 있습니다. 나는 Just Bash를 의미합니다. github.com/SumuduLansakara/JustBash
Sumudu

이것을 unix.stackexchange.com 으로 옮기지 않아야 합니까?
Ethan

답변:


685

줄을 덮어 써서 이것을 구현할 수 있습니다. 터미널에 \r쓰지 않고 줄의 처음으로 돌아갈 때 사용하십시오 \n.

\n당신이 라인을 진행 완료되면 작성 하십시오.

사용 echo -ne:

  1. 하지 인쇄 \n
  2. 와 같은 이스케이프 시퀀스를 인식 \r합니다.

데모는 다음과 같습니다.

echo -ne '#####                     (33%)\r'
sleep 1
echo -ne '#############             (66%)\r'
sleep 1
echo -ne '#######################   (100%)\r'
echo -ne '\n'

아래 주석에서, puk은 긴 줄로 시작하여 짧은 줄을 작성하려는 경우이 "실패"를 언급합니다.이 경우 긴 줄의 길이를 덮어 써야합니다 (예 : 공백).


23
echo 설명서 페이지 에 따르면 (최소한 MacOS X에서는) sh / bash 는 "-n"을 허용하지 않는 자체 내장 echo 명령을 사용합니다. 따라서 동일한 작업을 수행하려면 \ r \ r
Justin Jenkins

51
이것을 출력하는 휴대용 방법은 printf대신에 사용하는 것입니다 echo.
Jens

9
printf의 경우 다음 형식을 사용해야합니다. printf "#### (50%%)\r", 작은 따옴표로 작동하지 않으며 퍼센트 부호를 이스케이프해야합니다.
nurettin

7
나는 이것을 얻지 못한다- "이 작업이 알려지지 않은 하드웨어에서 얼마나 오래 걸릴지 짐작할 수있을 것이다." pv 는 정답 IMO입니다 (그러나 막대 도 마찬가지입니다)
Stephen

19
문제는 파일 복사 예제와 함께 "진행률 표시 줄을 어떻게합니까?"였습니다. 파일 복사 작업의 거리를 계산하는 것이 아니라 "그래픽"문제에 중점을 두었습니다.
Mitch Haile

73

스피너를 만드는 방법에 관심이있을 수도 있습니다 .

Bash에서 스피너를 사용할 수 있습니까?

확실한!

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

루프가 반복 될 때마다 sp 문자열에 다음 문자가 표시되고 끝에 도달 할 때 줄 바꿈됩니다. (i는 표시 할 현재 문자의 위치이고 $ {# sp}는 sp 문자열의 길이입니다).

\ b 문자열은 'backspace'문자로 대체됩니다. 또는 \ r을 사용하여 줄의 처음으로 돌아갈 수 있습니다.

속도를 늦추려면 루프 내부 (printf 뒤)에 휴면 명령을 입력하십시오.

POSIX는 다음과 같습니다.

sp='/-\|'
printf ' '
while true; do
    printf '\b%.1s' "$sp"
    sp=${sp#?}${sp%???}
done

많은 작업을 수행하는 루프가 이미있는 경우 각 반복 시작시 다음 함수를 호출하여 스피너를 업데이트 할 수 있습니다.

sp="/-\|"
sc=0
spin() {
   printf "\b${sp:sc++:1}"
   ((sc==${#sp})) && sc=0
}
endspin() {
   printf "\r%s\n" "$@"
}

until work_done; do
   spin
   some_work ...
done
endspin

15
훨씬 짧은 버전, 완전히 휴대용 *은 : while :;do for s in / - \\ \|; do printf "\r$s";sleep .1;done;done(* sleep의 int보다는 소수가 필요할 수 있음)
아담 카츠

1
@Daenyth. 감사. 친절하게 우리가 명령을 호출 해야하는 곳은 이전 코드를 사용하여 진행되고 있는지 확인해야합니까?
goro

@goro : 위의 some_work ...줄에서; 이 유용한 답변과 POSIX 준수에 중점을 둔 Adam Katz의 유용한 의견을 바탕으로 한 자세한 설명은 여기를 참조하십시오 .
mklement0

@AdamKatz : 그건 도움이되는, 휴대용 단순화하지만 Daenyth의 접근 방식과 일치하기 위해 회 전자를 기반으로해야합니다 \b보다는 \r, 그것은 것입니다 매우 라인의 시작에서 그 밖에는 작업 : while :; do for c in / - \\ \|; do printf '%s\b' "$c"; sleep 1; done; done-, 또는 경우 스피너 뒤에 커서를 표시 : 바람직하지 않은 것입니다printf ' ' && while :; do for c in / - \\ \|; do printf '\b%s' "$c"; sleep 1; done; done
mklement0은

1
@kaushal – Ctrl + C는 수동으로 중지합니다. 백그라운드 작업이있는 경우 PID ( job=$!)를 저장 한 후 다음과 같이 실행할 수 있습니다 while kill -0 $job 2>/dev/null;do ….sleep 15 & job=$!; while kill -0 $job 2>/dev/null; do for s in / - \\ \|; do printf "\r$s"; sleep .1; done; done
Adam Katz

48

일부 게시물은 명령의 진행 상황을 표시하는 방법을 보여주었습니다. 그것을 계산하기 위해, 당신은 얼마나 진행했는지 볼 필요가 있습니다. BSD 시스템에서 dd (1)와 같은 일부 명령은 SIGINFO신호를 받아들이고 진행 상황을보고합니다. Linux 시스템에서 일부 명령은와 유사하게 응답합니다 SIGUSR1. 이 기능이 사용 가능한 경우 입력을 파이프하여 dd처리 된 바이트 수를 모니터 할 수 있습니다.

또는 lsof파일 읽기 포인터의 오프셋을 확보하여 진행률을 계산하는 데 사용할 수 있습니다 . 지정된 프로세스 또는 파일 처리 진행률을 표시하는 pmonitor 라는 명령을 작성했습니다 . 그것으로 당신은 다음과 같은 일을 할 수 있습니다.

$ pmonitor -c gzip
/home/dds/data/mysql-2015-04-01.sql.gz 58.06%

이전 버전의 Linux 및 FreeBSD 셸 스크립트가 내 블로그에 나타납니다 .


: 이것은 내가 항상 내 "통계"명령이 다르게이 스크립트의 내 (리눅스) 버전 조금 작동 생각 :-) 태양 광 발전을 통해 파이프 것을 잊지 굉장 gist.github.com/unhammer/b0ab6a6aa8e1eeaf236b을
unhammer

좋은 게시물, awk놀이에 항상 그것을 사랑 해요 !
ShellFish

대단해! 멋진 스크립트 감사합니다!
thebeagle

47

다른 날에 쓴 쉬운 진행률 표시 줄 기능이 있습니다.

#!/bin/bash
# 1. Create ProgressBar function
# 1.1 Input is currentState($1) and totalState($2)
function ProgressBar {
# Process data
    let _progress=(${1}*100/${2}*100)/100
    let _done=(${_progress}*4)/10
    let _left=40-$_done
# Build progressbar string lengths
    _fill=$(printf "%${_done}s")
    _empty=$(printf "%${_left}s")

# 1.2 Build progressbar strings and print the ProgressBar line
# 1.2.1 Output example:                           
# 1.2.1.1 Progress : [########################################] 100%
printf "\rProgress : [${_fill// /#}${_empty// /-}] ${_progress}%%"

}

# Variables
_start=1

# This accounts as the "totalState" variable for the ProgressBar function
_end=100

# Proof of concept
for number in $(seq ${_start} ${_end})
do
    sleep 0.1
    ProgressBar ${number} ${_end}
done
printf '\nFinished!\n'

또는
https://github.com/fearside/ProgressBar/에서


1.2.1.1 이하의 내용을 설명해 주시겠습니까? _fill 및 _empty 변수로 sed 대체를 수행하고 있습니까? 혼란 스러워요.
Chirag

sed를 사용하는 대신 bash 내부 "Substring Replacement"를 사용하는 im은 쉬운 작업이므로 bash의 내부 기능을 사용하는 것이 좋습니다. 코드도 좋아 보인다. :-) tldp.org/LDP/abs/html/string-manipulation.html을 확인 하고 하위 문자열 대체를 검색 하십시오 .
fearside

$ {_ fill}은 $ {_ done} 개의 공백으로 할당됩니다. 이것은 아름답다. 잘 했어 나는 이것을 모든 bash 스크립트에서 확실히 사용할 것이다. haha
Chirag

훌륭한 작품 @fearside! 속도를 향상시키기 위해 _progress가 마지막 값에서 변경되지 않았을 때 건너 뛰기를 약간 조정했습니다. github.com/enobufs/bash-tools/blob/master/bin/progbar
enobufs

단. 사각형으로 대시를 변경하면 좀 더 전문적인 모양과 느낌을 제공합니다 :printf "\rProgress : [${_fill// /▇}${_empty// / }] ${_progress}%%"
메디 LAMRANI

44

리눅스 명령 pv를 사용하십시오 :

http://linux.die.net/man/1/pv

스트림 중간에 있으면 크기를 알지 못하지만 속도와 총계를 제공하며 거기에서 걸리는 시간을 파악하고 피드백을 얻는 데 필요한 시간을 알 수 있습니다.


32

선택한 답변보다 더 섹시한 것을 찾고 있었고 내 스크립트도 마찬가지였습니다.

시사

진행중인 progress-bar.sh

출처

나는 github에 넣었다.progress-bar.sh

progress-bar() {
  local duration=${1}


    already_done() { for ((done=0; done<$elapsed; done++)); do printf "▇"; done }
    remaining() { for ((remain=$elapsed; remain<$duration; remain++)); do printf " "; done }
    percentage() { printf "| %s%%" $(( (($elapsed)*100)/($duration)*100/100 )); }
    clean_line() { printf "\r"; }

  for (( elapsed=1; elapsed<=$duration; elapsed++ )); do
      already_done; remaining; percentage
      sleep 1
      clean_line
  done
  clean_line
}

용법

 progress-bar 100

1
프로세스 길이를 알 수없는 일부 처리에 이것이 어떻게 통합되는지 이해하지 못합니다. 파일 압축 풀기 등 프로세스가 일찍 완료된 경우 진행률 표시 줄을 중지하는 방법
1 월

나는 사용법이 있어야한다고 생각합니다progress-bar 100
jirarium

실제로 매력적인 발전. ssh를 통해 원격 서버에서 장기간의 작업을 처리하는 기능에 어떻게 연결할 수 있습니까? 원격 서버의 업그레이드 타이밍을 어떻게 측정 할 수 있습니까?
익명의

1
@faceless 그것은이 코드의 범위에 있지 않습니다 당신이 시간을 제공하고 카운트 다운
Édouard Lopez

1
@Fusion 현대 쉘에 안전해야하는 유니 코드 문자 (U + 2587 LOWER SEVEN EIGHTHS BLOCK)입니다. 당신의 envs에 시도하십시오
Édouard Lopez

18

GNU tar 에는 간단한 진행 표시 줄의 기능을 제공하는 유용한 옵션이 있습니다.

(...) 사용 가능한 다른 검사 점 작업은 'dot'(또는 '.')입니다. tar는 표준 목록 스트림에 단일 점을 인쇄하도록 지시합니다. 예 :

$ tar -c --checkpoint=1000 --checkpoint-action=dot /var
...

다음과 같은 방법으로 동일한 효과를 얻을 수 있습니다.

$ tar -c --checkpoint=.1000 /var

가장 간단한 방법은 +1입니다! 인쇄 된 점이 없으면 예를 들어 숫자를 줄이십시오 --checkpoint=.10. 로 추출 할 때도 효과적입니다 tar -xz.
Noam Manos

13

pipeview (pv) 유틸리티를 사용하여 시스템에서 작동하는 간단한 방법입니다.

srcdir=$1
outfile=$2


tar -Ocf - $srcdir | pv -i 1 -w 50 -berps `du -bs $srcdir | awk '{print $1}'` | 7za a -si $outfile

13

비슷한 것을 보지 못했고 여기의 모든 사용자 정의 함수는 렌더링에만 중점을 둔 것처럼 보입니다.이 질문은 사소하지 않기 때문에 단계별 설명이있는 매우 간단한 POSIX 호환 솔루션입니다.

TL; DR

진행률 표시 줄을 렌더링하는 것은 매우 쉽습니다. 렌더링해야하는 양을 추정하는 것은 다른 문제입니다. 진행률 표시 줄을 렌더링 (애니메이션)하는 방법입니다.이 예제를 파일로 복사하여 붙여 넣어 실행할 수 있습니다.

#!/bin/sh

BAR='####################'   # this is full bar, e.g. 20 chars

for i in {1..20}; do
    echo -ne "\r${BAR:0:$i}" # print $i chars of $BAR from 0 position
    sleep .1                 # wait 100ms between "frames"
done
  • {1..20} -1에서 20 사이의 값
  • echo -n -끝에 줄 바꿈없이 인쇄
  • echo -e -인쇄 중 특수 문자 해석
  • "\r" -캐리지 리턴, 줄의 처음으로 돌아가는 특수 문자

어떤 속도로든 컨텐츠를 렌더링 할 수 있으므로이 방법은 매우 보편적입니다.

전체 답변

문제의 핵심은 $i값 을 결정하는 방법, 즉 진행률 표시 줄이 표시되는 양입니다. 위의 예제 for에서는 원리를 설명하기 위해 루프에서 증가 시켰지만 실제 응용 프로그램은 무한 루프를 사용하고 $i각 반복 에서 변수를 계산합니다 . 상기 계산을하려면 다음 성분이 필요합니다.

  1. 수행해야 할 작업량
  2. 지금까지 얼마나 많은 작업을 수행했는지

의 경우 cp그 소스 파일과 대상 파일의 크기의 크기를해야합니다 :

#!/bin/sh

$src=/path/to/source/file
$tgt=/path/to/target/file

cp "$src" "$tgt" &                     # the & forks the `cp` process so the rest
                                       # of the code runs without waiting (async)

BAR='####################'

src_size=$(stat -c%s "$src")           # how much there is to do

while true; do
    tgt_size=$(stat -c%s "$tgt")       # how much has been done so far
    i=$(( $tgt_size * 20 / $src_size ))
    echo -ne "\r${BAR:0:$i}"
    if [ $tgt_size == $src_size ]; then
        echo ""                        # add a new line at the end
        break;                         # break the loop
    fi
    sleep .1
done
  • stat -파일 통계 확인
  • -c -형식화 된 값을 반환
  • %s - 총합 크기

파일 압축 해제와 같은 작업의 경우 소스 크기를 계산하는 것이 약간 더 어렵지만 압축되지 않은 파일의 크기를 얻는 것만 큼 쉽습니다.

#!/bin/sh
src_size=$(gzip -l "$src" | tail -n1 | tr -s ' ' | cut -d' ' -f3)
  • gzip -l -우편 아카이브에 대한 정보 표시
  • tail -n1 -바닥에서 한 줄로 작업
  • tr -s ' ' -여러 공간을 하나로 번역하십시오 (압착하십시오).
  • cut -d' ' -f3 -공백으로 구분 된 세 번째 열을 자릅니다.

그래도 문제의 고기가 있습니다. 이 솔루션은 점점 덜 일반적입니다. 실제 진행 상황에 대한 모든 계산은 시각화하려는 도메인에 밀접하게 바인딩되어 있습니다. 단일 파일 작업, 타이머 카운트 다운, 디렉토리의 파일 수 증가, 여러 파일에서의 작업 등입니다. 재사용 할 수 없습니다. 재사용 가능한 유일한 부분은 진행률 표시 줄 렌더링입니다. 이를 재사용하려면 추상화하고 파일 (예 :)에 저장 /usr/lib/progress_bar.sh한 다음 도메인에 특정한 입력 값을 계산하는 함수를 정의해야합니다. 이것은 일반 코드가 어떻게 생겼는지 보여줍니다 $BAR.

#!/bin/sh

BAR_length=50
BAR_character='#'
BAR=$(printf "%${BAR_length}s" | tr ' ' $BAR_character)

work_todo=$(get_work_todo)             # how much there is to do

while true; do
    work_done=$(get_work_done)         # how much has been done so far
    i=$(( $work_done * $BAR_length / $work_todo ))
    echo -ne "\r${BAR:0:$i}"
    if [ $work_done == $work_todo ]; then
        echo ""
        break;
    fi
    sleep .1
done
  • printf -주어진 형식으로 물건을 인쇄하기위한 내장
  • printf '%50s' -아무것도 인쇄하지 않고 50 칸으로 채 웁니다.
  • tr ' ' '#' -모든 공간을 해시 표시로 변환

그리고 이것이 당신이 그것을 사용하는 방법입니다 :

#!/bin/sh

src=/path/to/source/file
tgt=/path/to/target/file

function get_work_todo() {
    echo $(stat -c%s "$src")
}

function get_work_done() {
    [ -e "$tgt" ] &&                   # if target file exists
        echo $(stat -c%s "$tgt") ||    # echo its size, else
        echo 0                         # echo zero
}

cp "$src" "$tgt" &                     # copy in the background

source /usr/lib/progress_bar.sh        # execute the progress bar

분명히 그것은 함수에 싸여 파이프 스트림과 함께 작동하도록 다시 쓰여지고 독에 관계없이 다른 언어로 다시 쓰여질 수 있습니다.


1
가장 간단한 것을 원하는 사람들을 위해 방금 cprn 첫 번째 대답으로 내 것을 만들었습니다. 바보 같은 비례 규칙을 사용하여 막대를 그리는 함수의 매우 간단한 진행률 막대입니다. pastebin.com/9imhRLYX
YCN-


9

APT 스타일 진행률 표시 줄 (정상 출력을 중단하지 않음)

여기에 이미지 설명을 입력하십시오

편집 : 업데이트 된 버전은 내 github 페이지를 확인 하십시오.

이 질문에 대한 답변에 만족하지 않았습니다. 내가 개인적으로 찾고 있던 것은 APT에서 볼 수있는 멋진 진행률 표시 줄이었습니다.

나는 APT에 대한 C 소스 코드를 보았고 bash에 대한 동등한 코드를 작성하기로 결정했다.

이 진행률 표시 줄은 터미널 하단에 잘 유지되며 터미널로 전송되는 출력을 방해하지 않습니다.

막대는 현재 100 자 너비로 고정되어 있습니다. 터미널의 크기에 맞게 확장하려면이 작업도 상당히 쉽습니다 (github 페이지의 업데이트 된 버전이이를 잘 처리합니다).

스크립트를 여기에 게시하겠습니다. 사용 예 :

source ./progress_bar.sh
echo "This is some output"
setup_scroll_area
sleep 1
echo "This is some output 2"
draw_progress_bar 10
sleep 1
echo "This is some output 3"
draw_progress_bar 50
sleep 1
echo "This is some output 4"
draw_progress_bar 90
sleep 1
echo "This is some output 5"
destroy_scroll_area

스크립트 (대신 github의 버전을 대신 권장합니다) :

#!/bin/bash

# This code was inspired by the open source C code of the APT progress bar
# http://bazaar.launchpad.net/~ubuntu-branches/ubuntu/trusty/apt/trusty/view/head:/apt-pkg/install-progress.cc#L233

#
# Usage:
# Source this script
# setup_scroll_area
# draw_progress_bar 10
# draw_progress_bar 90
# destroy_scroll_area
#


CODE_SAVE_CURSOR="\033[s"
CODE_RESTORE_CURSOR="\033[u"
CODE_CURSOR_IN_SCROLL_AREA="\033[1A"
COLOR_FG="\e[30m"
COLOR_BG="\e[42m"
RESTORE_FG="\e[39m"
RESTORE_BG="\e[49m"

function setup_scroll_area() {
    lines=$(tput lines)
    let lines=$lines-1
    # Scroll down a bit to avoid visual glitch when the screen area shrinks by one row
    echo -en "\n"

    # Save cursor
    echo -en "$CODE_SAVE_CURSOR"
    # Set scroll region (this will place the cursor in the top left)
    echo -en "\033[0;${lines}r"

    # Restore cursor but ensure its inside the scrolling area
    echo -en "$CODE_RESTORE_CURSOR"
    echo -en "$CODE_CURSOR_IN_SCROLL_AREA"

    # Start empty progress bar
    draw_progress_bar 0
}

function destroy_scroll_area() {
    lines=$(tput lines)
    # Save cursor
    echo -en "$CODE_SAVE_CURSOR"
    # Set scroll region (this will place the cursor in the top left)
    echo -en "\033[0;${lines}r"

    # Restore cursor but ensure its inside the scrolling area
    echo -en "$CODE_RESTORE_CURSOR"
    echo -en "$CODE_CURSOR_IN_SCROLL_AREA"

    # We are done so clear the scroll bar
    clear_progress_bar

    # Scroll down a bit to avoid visual glitch when the screen area grows by one row
    echo -en "\n\n"
}

function draw_progress_bar() {
    percentage=$1
    lines=$(tput lines)
    let lines=$lines
    # Save cursor
    echo -en "$CODE_SAVE_CURSOR"

    # Move cursor position to last row
    echo -en "\033[${lines};0f"

    # Clear progress bar
    tput el

    # Draw progress bar
    print_bar_text $percentage

    # Restore cursor position
    echo -en "$CODE_RESTORE_CURSOR"
}

function clear_progress_bar() {
    lines=$(tput lines)
    let lines=$lines
    # Save cursor
    echo -en "$CODE_SAVE_CURSOR"

    # Move cursor position to last row
    echo -en "\033[${lines};0f"

    # clear progress bar
    tput el

    # Restore cursor position
    echo -en "$CODE_RESTORE_CURSOR"
}

function print_bar_text() {
    local percentage=$1

    # Prepare progress bar
    let remainder=100-$percentage
    progress_bar=$(echo -ne "["; echo -en "${COLOR_FG}${COLOR_BG}"; printf_new "#" $percentage; echo -en "${RESTORE_FG}${RESTORE_BG}"; printf_new "." $remainder; echo -ne "]");

    # Print progress bar
    if [ $1 -gt 99 ]
    then
        echo -ne "${progress_bar}"
    else
        echo -ne "${progress_bar}"
    fi
}

printf_new() {
    str=$1
    num=$2
    v=$(printf "%-${num}s" "$str")
    echo -ne "${v// /$str}"
}

7

이를 통해 명령이 여전히 실행 중임을 시각화 할 수 있습니다.

while :;do echo -n .;sleep 1;done &
trap "kill $!" EXIT  #Die with parent if we die prematurely
tar zxf packages.tar.gz; # or any other command here
kill $! && trap " " EXIT #Kill the loop and unset the trap or else the pid might get reassigned and we might end up killing a completely different process

백그라운드에서 실행되고 "."를 에코 하는 무한 while 루프 가 생성됩니다 . 매 초. .셸에 표시 됩니다. tar명령 또는 원하는 명령을 실행하십시오 . 다음 실행하는 명령이 완료가되면 죽일 수 는 IS - 백그라운드에서 실행중인 마지막 작업 루프 동안 무한 .


실행 중에 백그라운드에서 다른 작업을 시작할 수없고 진행률 루프 대신 종료 될 수 없습니까?
Centimane

나는 이것이 당신이 이것을 스크립트에 넣을 것이라고 생각합니다. 그래서 이것은 그 스크립트의 출구 만 트랩합니다.
Iguananaut

1
나는이 명령을 좋아하고 내 파일에서 사용하고 있습니다. 나는 그것이 어떻게 작동하는지 실제로 이해하지 못하기 때문에 조금 불안합니다. 첫 번째와 세 번째 줄은 이해하기 쉽지만 여전히 확실하지 않습니다. 나는 이것이 오래된 대답이라는 것을 알고 있지만 프로그래밍 할 때 초보자를 대상으로 다른 설명을 얻을 수있는 방법이 있습니까?
Felipe

1
이것은 유일한 진정한 답변이며, 다른 사람들은 아무것도 의미하지 않으며 실제 일회성 추적 할 수없는 (거의 모든) 프로그램에는 사용되지 않는 Scripting 101 장난감 진행률 표시 줄입니다. 감사합니다.
bekce

@Felipe, while 루프는 백그라운드 프로세스입니다. $! 첫 번째 트랩에서 해당 백그라운드 프로세스의 프로세스 ID를 캡처하고 현재 / 부모 프로세스가 종료되면 백그라운드 프로세스도 종료되고 중단되지 않도록합니다. kill 명령은 긴 명령 또는 명령이 끝나면 백그라운드 프로세스를 종료합니다.
floydn

7

여기 어떻게 보일지

파일 업로드

[##################################################] 100% (137921 / 137921 bytes)

작업이 완료되기를 기다리는 중

[#########################                         ] 50% (15 / 30 seconds)

그것을 구현하는 간단한 기능

스크립트에 복사하여 붙여 넣기 만하면됩니다. 작동하기 위해 다른 것이 필요하지 않습니다.

PROGRESS_BAR_WIDTH=50  # progress bar length in characters

draw_progress_bar() {
  # Arguments: current value, max value, unit of measurement (optional)
  local __value=$1
  local __max=$2
  local __unit=${3:-""}  # if unit is not supplied, do not display it

  # Calculate percentage
  if (( $__max < 1 )); then __max=1; fi  # anti zero division protection
  local __percentage=$(( 100 - ($__max*100 - $__value*100) / $__max ))

  # Rescale the bar according to the progress bar width
  local __num_bar=$(( $__percentage * $PROGRESS_BAR_WIDTH / 100 ))

  # Draw progress bar
  printf "["
  for b in $(seq 1 $__num_bar); do printf "#"; done
  for s in $(seq 1 $(( $PROGRESS_BAR_WIDTH - $__num_bar ))); do printf " "; done
  printf "] $__percentage%% ($__value / $__max $__unit)\r"
}

사용 예

여기에서 파일을 업로드하고 각 반복마다 진행률 표시 줄을 다시 그립니다. 최대 값과 현재 값의 두 가지 값을 얻을 수있는 한 실제로 수행되는 작업은 중요하지 않습니다.

아래 예에서 최대 값은 file_size이며 현재 값은 일부 함수에 의해 제공되며 호출 uploaded_bytes됩니다.

# Uploading a file
file_size=137921

while true; do
  # Get current value of uploaded bytes
  uploaded_bytes=$(some_function_that_reports_progress)

  # Draw a progress bar
  draw_progress_bar $uploaded_bytes $file_size "bytes"

  # Check if we reached 100%
  if [ $uploaded_bytes == $file_size ]; then break; fi
  sleep 1  # Wait before redrawing
done
# Go to the newline at the end of upload
printf "\n"

깔끔하고 간단한 기능. 고마워요!
안드레아스 크래프트

이것이 내가 찾고있는 것입니다! 고마워요 :)
wajdi_jurry

4

대부분의 유닉스 명령어는 당신이 할 수있는 직접적인 피드백을 제공하지 않습니다. 일부는 stdout 또는 stderr에서 사용할 수있는 출력을 제공합니다.

tar와 같은 경우 -v 스위치를 사용하여 읽은 각 줄에 대해 작은 애니메이션을 업데이트하는 프로그램으로 출력을 파이프 할 수 있습니다. tar는 파일 목록을 작성함에 따라 프로그램에서 애니메이션을 업데이트 할 수 있습니다. 완료율을 달성하려면 파일 수를 알고 행 수를 계산해야합니다.

cp는 내가 아는 한 이런 종류의 출력을 제공하지 않습니다. cp의 진행 상황을 모니터링하려면 소스 및 대상 파일을 모니터링하고 대상의 크기를 확인해야합니다. 파일 크기를 얻기 위해 stat (2) 시스템 호출을 사용하여 작은 c 프로그램을 작성할 수 있습니다. 소스 크기를 읽은 다음 대상 파일을 폴링하고 현재까지 기록 된 파일 크기를 기준으로 완료율 (%)을 업데이트합니다.


4

내 솔루션에는 현재 압축되지 않은 타르볼의 백분율이 표시됩니다. 2GB 루트 파일 시스템 이미지를 작성할 때 이것을 사용합니다. 당신은 정말로 이런 것들에 대한 진행 표시 줄이 필요합니다. 내가하는 것은 gzip --listtarball의 전체 압축되지 않은 크기를 얻는 데 사용 하는 것입니다 . 그로부터 파일을 100 부분으로 나누는 데 필요한 차단 계수를 계산합니다. 마지막으로 각 블록에 대한 검사 점 메시지를 인쇄합니다. 2GB 파일의 경우 약 10MB의 블록이 제공됩니다. 그것이 너무 크면 BLOCKING_FACTOR를 10 또는 100으로 나눌 수 있지만 백분율로 예쁜 출력을 인쇄하는 것이 더 어렵습니다.

Bash를 사용한다고 가정하면 다음 쉘 기능을 사용할 수 있습니다

untar_progress () 
{ 
  TARBALL=$1
  BLOCKING_FACTOR=$(gzip --list ${TARBALL} |
    perl -MPOSIX -ane '$.==2 && print ceil $F[1]/50688')
  tar --blocking-factor=${BLOCKING_FACTOR} --checkpoint=1 \
    --checkpoint-action='ttyout=Wrote %u%  \r' -zxf ${TARBALL}
}

좋은 해결책이지만 디렉토리를 압축하고 싶을 때 어떻게합니까?
Samir Sadek

4

우선 모든 막대가 유일한 파이프 진행 미터는 아닙니다. 다른 것 (아마도 더 알려질 수도 있음)은 pv (파이프 뷰어)입니다.

두 번째로 bar 및 pv는 예를 들어 다음과 같이 사용할 수 있습니다.

$ bar file1 | wc -l 
$ pv file1 | wc -l

또는:

$ tail -n 100 file1 | bar | wc -l
$ tail -n 100 file1 | pv | wc -l

copy file1 file2와 같이 인수로 주어진 파일로 작업하는 명령에서 bar 및 pv를 사용하려는 경우 유용한 트릭은 프로세스 대체 를 사용 하는 것입니다 .

$ copy <(bar file1) file2
$ copy <(pv file1) file2

프로세스 대체는 임시 fifo 파이프 파일 / dev / fd /를 작성하고 실행 된 프로세스 (괄호 안의)에서 stdout을이 파이프를 통해 연결하고 복사하면 일반 파일처럼 볼 수 있습니다 (한 예외는 읽을 수만 있음) 전달).

최신 정보:

bar 명령 자체는 복사도 가능합니다. 남자 바 후 :

bar --in-file /dev/rmt/1cbn --out-file \
     tape-restore.tar --size 2.4g --buffer-size 64k

그러나 프로세스 대체는 더 일반적인 방법입니다. 그것은 cp 프로그램 자체를 사용합니다.


3

--gauge 매개 변수 와 함께 대화 상자 를 사용하는 것을 선호합니다 . .deb 패키지 설치 및 많은 배포판의 기타 기본 구성 항목에서 매우 자주 사용됩니다. 따라서 휠을 다시 발명 할 필요가 없습니다 ... 다시

1에서 100 @stdin까지 int 값을 입력하십시오. 하나의 기본적이고 어리석은 예 :

for a in {1..100}; do sleep .1s; echo $a| dialog --gauge "waiting" 7 30; done

요리 목적 으로이 / bin / Wait 파일 (chmod u + x perms 포함)이 있습니다 : P

#!/bin/bash
INIT=`/bin/date +%s`
NOW=$INIT
FUTURE=`/bin/date -d "$1" +%s`
[ $FUTURE -a $FUTURE -eq $FUTURE ] || exit
DIFF=`echo "$FUTURE - $INIT"|bc -l`

while [ $INIT -le $FUTURE -a $NOW -lt $FUTURE ]; do
    NOW=`/bin/date +%s`
    STEP=`echo "$NOW - $INIT"|bc -l`
    SLEFT=`echo "$FUTURE - $NOW"|bc -l`
    MLEFT=`echo "scale=2;$SLEFT/60"|bc -l`
    TEXT="$SLEFT seconds left ($MLEFT minutes)";
    TITLE="Waiting $1: $2"
    sleep 1s
    PTG=`echo "scale=0;$STEP * 100 / $DIFF"|bc -l`
    echo $PTG| dialog --title "$TITLE" --gauge "$TEXT" 7 72
done

if [ "$2" == "" ]; then msg="Espera terminada: $1";audio="Listo";
else msg=$2;audio=$2;fi 

/usr/bin/notify-send --icon=stock_appointment-reminder-excl "$msg"
espeak -v spanish "$audio"

그래서 나는 넣을 수 있습니다 :

Wait "34 min" "warm up the oven"

또는

Wait "dec 31" "happy new year"


2

나를 위해 사용하기 가장 쉽고 지금까지 가장 잘 보이는 것은 명령 pv이거나 bar이미 쓴 사람과 같습니다.

예를 들어 다음과 같이 전체 드라이브를 백업해야합니다. dd

일반적으로 사용 dd if="$input_drive_path" of="$output_file_path"

으로 pv당신과 같이 그것을 만들 수 있습니다 :

dd if="$input_drive_path" | pv | dd of="$output_file_path"

진행 상황은 다음과 같이 직접 진행됩니다 STDOUT.

    7.46GB 0:33:40 [3.78MB/s] [  <=>                                            ]

완료되면 요약이 나타납니다.

    15654912+0 records in
    15654912+0 records out
    8015314944 bytes (8.0 GB) copied, 2020.49 s, 4.0 MB/s

타이머 카운트 다운, 텍스트 파일에서의 위치, 앱 설치, 런타임 설정 등과 같은 다양한 프로세스의 진행 상황 을 사용 pv하거나 bar시각화 할 수 있습니까 ?
cprn

2

많은 답변은 인쇄 명령을 작성하는 방법을 설명합니다 '\r' + $some_sort_of_progress_msg. 문제는 때때로 초당 수백 개의 업데이트를 인쇄하면 프로세스 속도가 느려진다는 것입니다.

그러나 프로세스에서 출력을 생성하는 경우 (예 : 7z a -r newZipFile myFolder압축 할 때 각 파일 이름이 출력 됨) 더 간단하고 빠르고 고통스럽지 않고 사용자 정의 할 수있는 솔루션이 존재합니다.

파이썬 모듈을 설치합니다 tqdm.

$ sudo pip install tqdm
$ # now have fun
$ 7z a -r -bd newZipFile myFolder | tqdm >> /dev/null
$ # if we know the expected total, we can have a bar!
$ 7z a -r -bd newZipFile myFolder | grep -o Compressing | tqdm --total $(find myFolder -type f | wc -l) >> /dev/null

도움말 : tqdm -h. 더 많은 옵션을 사용하는 예 :

$ find / -name '*.py' -exec cat \{} \; | tqdm --unit loc --unit_scale True | wc -l

보너스 tqdm로 파이썬 코드로 이터 러블을 래핑 하는 데 사용할 수도 있습니다 .

https://github.com/tqdm/tqdm/blob/master/README.rst#module


"더 많은 옵션"을 사용한 귀하의 예는 효과가 없다고 생각합니다. tqdmSTDOUT을 wc -l파이프 로 통과시키는 것 같습니다 . 아마도 그것을 피하고 싶을 것입니다.
cprn

1
입력 을로 파이프하는 동안 @cprn tqdm이 진행 상태를 표시 합니다 . 이 경우 whould 는 포함되지 않은 것과 동일한 입력을받습니다 . STDERRSTDINSTDOUTwc -ltqdm
casper.dcl

아 이해가 되네요 설명해 주셔서 감사합니다.
cprn

2

Edouard Lopez의 작업을 기반으로 화면 크기에 맞는 진행률 표시 줄을 만들었습니다. 확인 해봐.

여기에 이미지 설명을 입력하십시오

Git Hub 에도 게시되어 있습니다.

#!/bin/bash
#
# Progress bar by Adriano Pinaffo
# Available at https://github.com/adriano-pinaffo/progressbar.sh
# Inspired on work by Edouard Lopez (https://github.com/edouard-lopez/progress-bar.sh)
# Version 1.0
# Date April, 28th 2017

function error {
  echo "Usage: $0 [SECONDS]"
  case $1 in
    1) echo "Pass one argument only"
    exit 1
    ;;
    2) echo "Parameter must be a number"
    exit 2
    ;;
    *) echo "Unknown error"
    exit 999
  esac
}

[[ $# -ne 1 ]] && error 1
[[ $1 =~ ^[0-9]+$ ]] || error 2

duration=${1}
barsize=$((`tput cols` - 7))
unity=$(($barsize / $duration))
increment=$(($barsize%$duration))
skip=$(($duration/($duration-$increment)))
curr_bar=0
prev_bar=
for (( elapsed=1; elapsed<=$duration; elapsed++ ))
do
  # Elapsed
prev_bar=$curr_bar
  let curr_bar+=$unity
  [[ $increment -eq 0 ]] || {  
    [[ $skip -eq 1 ]] &&
      { [[ $(($elapsed%($duration/$increment))) -eq 0 ]] && let curr_bar++; } ||
    { [[ $(($elapsed%$skip)) -ne 0 ]] && let curr_bar++; }
  }
  [[ $elapsed -eq 1 && $increment -eq 1 && $skip -ne 1 ]] && let curr_bar++
  [[ $(($barsize-$curr_bar)) -eq 1 ]] && let curr_bar++
  [[ $curr_bar -lt $barsize ]] || curr_bar=$barsize
  for (( filled=0; filled<=$curr_bar; filled++ )); do
    printf "▇"
  done

  # Remaining
  for (( remain=$curr_bar; remain<$barsize; remain++ )); do
    printf " "
  done

  # Percentage
  printf "| %s%%" $(( ($elapsed*100)/$duration))

  # Return
  sleep 1
  printf "\r"
done
printf "\n"
exit 0

즐겨



1

이것은 gnome zenity를 사용하는 경우에만 적용됩니다. Zenity는 스크립트를 bash하기위한 훌륭한 기본 인터페이스를 제공합니다. https://help.gnome.org/users/zenity/stable/

Zenity 진행률 표시 줄 예 :

#!/bin/sh
(
echo "10" ; sleep 1
echo "# Updating mail logs" ; sleep 1
echo "20" ; sleep 1
echo "# Resetting cron jobs" ; sleep 1
echo "50" ; sleep 1
echo "This line will just be ignored" ; sleep 1
echo "75" ; sleep 1
echo "# Rebooting system" ; sleep 1
echo "100" ; sleep 1
) |
zenity --progress \
  --title="Update System Logs" \
  --text="Scanning mail logs..." \
  --percentage=0

if [ "$?" = -1 ] ; then
        zenity --error \
          --text="Update canceled."
fi

1

char 스크립트 를 반복하기 위해 쉘 스크립트에서 반복되는 문자 문자열 만들기 의 대답을 사용했습니다 . 진행률 표시 줄을 표시 해야하는 스크립트 (예 : 많은 파일을 통과하지만 큰 tar 파일 또는 복사 작업에는 유용하지 않은 루프)에 대해 상대적으로 작은 bash 버전 이 두 개 있습니다. 더 빠른 것은 두 개의 기능으로 구성되는데, 하나는 바 표시를 위해 문자열을 준비하는 것입니다.

preparebar() {
# $1 - bar length
# $2 - bar char
    barlen=$1
    barspaces=$(printf "%*s" "$1")
    barchars=$(printf "%*s" "$1" | tr ' ' "$2")
}

하나는 진행률 표시 줄을 표시합니다.

progressbar() {
# $1 - number (-1 for clearing the bar)
# $2 - max number
    if [ $1 -eq -1 ]; then
        printf "\r  $barspaces\r"
    else
        barch=$(($1*barlen/$2))
        barsp=$((barlen-barch))
        printf "\r[%.${barch}s%.${barsp}s]\r" "$barchars" "$barspaces"
    fi
}

다음과 같이 사용할 수 있습니다.

preparebar 50 "#"

즉, 50 개의 "#"문자로 바를위한 문자열을 준비한 후 다음을 수행합니다.

progressbar 35 80

35/80 비율에 해당하는 "#"문자 수가 표시됩니다.

[#####################                             ]

이 기능은 사용자 (또는 다른 프로그램)가 줄 바꿈을 인쇄 할 때까지 동일한 줄에 계속 막대를 표시합니다. -1을 첫 번째 매개 변수로 입력하면 막대가 지워집니다.

progressbar -1 80

느린 버전은 모두 하나의 기능에 있습니다.

progressbar() {
# $1 - number
# $2 - max number
# $3 - number of '#' characters
    if [ $1 -eq -1 ]; then
        printf "\r  %*s\r" "$3"
    else
        i=$(($1*$3/$2))
        j=$(($3-i))
        printf "\r[%*s" "$i" | tr ' ' '#'
        printf "%*s]\r" "$j"
    fi
}

(위와 동일한 예)와 같이 사용할 수 있습니다.

progressbar 35 80 50

stderr에 진행률 표시 줄이 필요한 경우 >&2각 printf 명령 끝에 추가하십시오 .


1

활동 진행률을 나타내려면 다음 명령을 시도하십시오.

while true; do sleep 0.25 && echo -ne "\r\\" && sleep 0.25 && echo -ne "\r|" && sleep 0.25 && echo -ne "\r/" && sleep 0.25 && echo -ne "\r-"; done;

또는

while true; do sleep 0.25 && echo -ne "\rActivity: \\" && sleep 0.25 && echo -ne "\rActivity: |" && sleep 0.25 && echo -ne "\rActivity: /" && sleep 0.25 && echo -ne "\rActivity: -"; done;

또는

while true; do sleep 0.25 && echo -ne "\r" && sleep 0.25 && echo -ne "\r>" && sleep 0.25 && echo -ne "\r>>" && sleep 0.25 && echo -ne "\r>>>"; sleep 0.25 && echo -ne "\r>>>>"; done;

또는

while true; do sleep .25 && echo -ne "\r:Active:" && sleep .25 && echo -ne "\r:aCtive:" && sleep .25 && echo -ne "\r:acTive:" && sleep .25 && echo -ne "\r:actIve:" && sleep .25 && echo -ne "\r:actiVe:" && sleep .25 && echo -ne "\r:activE:"; done;

while 루프 내에서 플래그 / 변수를 사용 하여 값 / 진행 상황을 확인하고 표시 할 수 있습니다 .


1

위에 나열된 제안을 사용하여 자체 진행률 표시 줄을 구현하기로 결정했습니다.

#!/usr/bin/env bash

main() {
  for (( i = 0; i <= 100; i=$i + 1)); do
    progress_bar "$i"
    sleep 0.1;
  done
  progress_bar "done"
  exit 0
}

progress_bar() {
  if [ "$1" == "done" ]; then
    spinner="X"
    percent_done="100"
    progress_message="Done!"
    new_line="\n"
  else
    spinner='/-\|'
    percent_done="${1:-0}"
    progress_message="$percent_done %"
  fi

  percent_none="$(( 100 - $percent_done ))"
  [ "$percent_done" -gt 0 ] && local done_bar="$(printf '#%.0s' $(seq -s ' ' 1 $percent_done))"
  [ "$percent_none" -gt 0 ] && local none_bar="$(printf '~%.0s' $(seq -s ' ' 1 $percent_none))"

  # print the progress bar to the screen
  printf "\r Progress: [%s%s] %s %s${new_line}" \
    "$done_bar" \
    "$none_bar" \
    "${spinner:x++%${#spinner}:1}" \
    "$progress_message"
}

main "$@"

1
좋은! 작동시키기 위해서는 줄 percent_none="$(( 100 - "$percent_done" ))"percent_none="$(( 100 - $percent_done))"
sergio

0

임베디드 시스템을 위해 순수한 쉘 버전을 사용했습니다.

  • / usr / bin / dd의 SIGUSR1 신호 처리 기능.

    기본적으로 'kill SIGUSR1 $ (pid_of_running_dd_process)'를 보내면 처리량 속도와 전송 된 양의 요약이 출력됩니다.

  • dd를 백그라운드로 업데이트 한 다음 정기적으로 업데이트를 요청하고 이전의 ftp 클라이언트와 같은 해시 틱을 생성합니다.

  • scp와 같은 비표준 친화적 프로그램의 대상으로 / dev / stdout 사용

결과적으로 모든 파일 전송 작업을 수행하고 모든 X 바이트에 대해 해시 마크를 얻는 구식 FTP '해시'출력과 같은 진행 업데이트를 얻을 수 있습니다.

이것은 프로덕션 품질 코드는 아니지만 아이디어를 얻습니다. 귀엽다고 생각합니다.

가치가있는 경우 실제 바이트 수는 해시 수에 올바르게 반영되지 않을 수 있습니다. 반올림 문제에 따라 하나 이상이있을 수 있습니다. 이것을 테스트 스크립트의 일부로 사용하지 마십시오. 눈에 띄는 사탕입니다. 그리고 그렇습니다, 나는 이것이 매우 비효율적이라는 것을 알고 있습니다-그것은 셸 스크립트이며 사과하지 않습니다.

끝에 wget, scp 및 tftp가 제공되는 예제. 데이터를 방출하는 모든 것이 작동해야합니다. 친숙하지 않은 프로그램에는 / dev / stdout을 사용하십시오.

#!/bin/sh
#
# Copyright (C) Nathan Ramella (nar+progress-script@remix.net) 2010 
# LGPLv2 license
# If you use this, send me an email to say thanks and let me know what your product
# is so I can tell all my friends I'm a big man on the internet!

progress_filter() {

        local START=$(date +"%s")
        local SIZE=1
        local DURATION=1
        local BLKSZ=51200
        local TMPFILE=/tmp/tmpfile
        local PROGRESS=/tmp/tftp.progress
        local BYTES_LAST_CYCLE=0
        local BYTES_THIS_CYCLE=0

        rm -f ${PROGRESS}

        dd bs=$BLKSZ of=${TMPFILE} 2>&1 \
                | grep --line-buffered -E '[[:digit:]]* bytes' \
                | awk '{ print $1 }' >> ${PROGRESS} &

        # Loop while the 'dd' exists. It would be 'more better' if we
        # actually looked for the specific child ID of the running 
        # process by identifying which child process it was. If someone
        # else is running dd, it will mess things up.

        # My PID handling is dumb, it assumes you only have one running dd on
        # the system, this should be fixed to just get the PID of the child
        # process from the shell.

        while [ $(pidof dd) -gt 1 ]; do

                # PROTIP: You can sleep partial seconds (at least on linux)
                sleep .5    

                # Force dd to update us on it's progress (which gets
                # redirected to $PROGRESS file.
                # 
                # dumb pid handling again
                pkill -USR1 dd

                local BYTES_THIS_CYCLE=$(tail -1 $PROGRESS)
                local XFER_BLKS=$(((BYTES_THIS_CYCLE-BYTES_LAST_CYCLE)/BLKSZ))

                # Don't print anything unless we've got 1 block or more.
                # This allows for stdin/stderr interactions to occur
                # without printing a hash erroneously.

                # Also makes it possible for you to background 'scp',
                # but still use the /dev/stdout trick _even_ if scp
                # (inevitably) asks for a password. 
                #
                # Fancy!

                if [ $XFER_BLKS -gt 0 ]; then
                        printf "#%0.s" $(seq 0 $XFER_BLKS)
                        BYTES_LAST_CYCLE=$BYTES_THIS_CYCLE
                fi
        done

        local SIZE=$(stat -c"%s" $TMPFILE)
        local NOW=$(date +"%s")

        if [ $NOW -eq 0 ]; then
                NOW=1
        fi

        local DURATION=$(($NOW-$START))
        local BYTES_PER_SECOND=$(( SIZE / DURATION ))
        local KBPS=$((SIZE/DURATION/1024))
        local MD5=$(md5sum $TMPFILE | awk '{ print $1 }')

        # This function prints out ugly stuff suitable for eval() 
        # rather than a pretty string. This makes it a bit more 
        # flexible if you have a custom format (or dare I say, locale?)

        printf "\nDURATION=%d\nBYTES=%d\nKBPS=%f\nMD5=%s\n" \
            $DURATION \
            $SIZE \
            $KBPS \
            $MD5
}

예 :

echo "wget"
wget -q -O /dev/stdout http://www.blah.com/somefile.zip | progress_filter

echo "tftp"
tftp -l /dev/stdout -g -r something/firmware.bin 192.168.1.1 | progress_filter

echo "scp"
scp user@192.168.1.1:~/myfile.tar /dev/stdout | progress_filter

괜찮은 아이디어, 파일 크기가 미리 지정되어 있다면 pv보다 더 많은 가치를 제공 할 수 있지만 맹목적으로 신호를 보내는 pidof dd것은 무섭습니다.

와 그 밖에 호출 시도 '벙어리 # 내 PID 처리이다'
synthesizerpatel는

$!에서 캡처 dd하고 기다릴 수 있습니다 [[ -e /proc/${DD_PID} ]].

0

시간 진행률 표시 줄을 표시 해야하는 경우 (표시 시간을 미리 알고) 다음과 같이 Python을 사용할 수 있습니다.

#!/bin/python
from time import sleep
import sys

if len(sys.argv) != 3:
    print "Usage:", sys.argv[0], "<total_time>", "<progressbar_size>"
    exit()

TOTTIME=float(sys.argv[1])
BARSIZE=float(sys.argv[2])

PERCRATE=100.0/TOTTIME
BARRATE=BARSIZE/TOTTIME

for i in range(int(TOTTIME)+1):
    sys.stdout.write('\r')
    s = "[%-"+str(int(BARSIZE))+"s] %d%% "
    sys.stdout.write(s % ('='*int(BARRATE*i), int(PERCRATE*i)))
    sys.stdout.flush()
    SLEEPTIME = 1.0
    if i == int(TOTTIME): SLEEPTIME = 0.1
    sleep(SLEEPTIME)
print ""

그런 다음 Python 스크립트를로 저장했다고 가정하면 progressbar.py다음 명령을 실행하여 bash 스크립트에서 진행률 표시 줄을 표시 할 수 있습니다.

python progressbar.py 10 50

진행률 막대가 크기로 표시됩니다. 50 문자와 10몇 초 동안 "실행 중" 됩니다.


0

나는 공포에 의해 제공된 답변을 바탕으로

RMAN 복원 진행률을 검색하기 위해 Oracle 데이터베이스에 연결합니다.

#!/bin/bash

 # 1. Create ProgressBar function
 # 1.1 Input is currentState($1) and totalState($2)
 function ProgressBar {
 # Process data
let _progress=(${1}*100/${2}*100)/100
let _done=(${_progress}*4)/10
let _left=40-$_done
# Build progressbar string lengths
_fill=$(printf "%${_done}s")
_empty=$(printf "%${_left}s")

# 1.2 Build progressbar strings and print the ProgressBar line
# 1.2.1 Output example:
# 1.2.1.1 Progress : [########################################] 100%
printf "\rProgress : [${_fill// /#}${_empty// /-}] ${_progress}%%"

}

function rman_check {
sqlplus -s / as sysdba <<EOF
set heading off
set feedback off
select
round((sofar/totalwork) * 100,0) pct_done
from
v\$session_longops
where
totalwork > sofar
AND
opname NOT LIKE '%aggregate%'
AND
opname like 'RMAN%';
exit
EOF
}

# Variables
_start=1

# This accounts as the "totalState" variable for the ProgressBar function
_end=100

_rman_progress=$(rman_check)
#echo ${_rman_progress}

# Proof of concept
#for number in $(seq ${_start} ${_end})

while [ ${_rman_progress} -lt 100 ]
do

for number in _rman_progress
do
sleep 10
ProgressBar ${number} ${_end}
done

_rman_progress=$(rman_check)

done
printf '\nFinished!\n'

0
#!/bin/bash

function progress_bar() {
    bar=""
    total=10
    [[ -z $1 ]] && input=0 || input=${1}
    x="##"
   for i in `seq 1 10`; do
        if [ $i -le $input ] ;then
            bar=$bar$x
        else
            bar="$bar  "
       fi
    done
    #pct=$((200*$input/$total % 2 + 100*$input/$total))
    pct=$(($input*10))
    echo -ne "Progress : [ ${bar} ] (${pct}%) \r"    
    sleep 1
    if [ $input -eq 10 ] ;then
        echo -ne '\n'
    fi

}

막대 수에 대해 1-10과 같은 스케일로 이것을 그리는 함수를 만들 수 있습니다.

progress_bar 1
echo "doing something ..."
progress_bar 2
echo "doing something ..."
progress_bar 3
echo "doing something ..."
progress_bar 8
echo "doing something ..."
progress_bar 10

0
#!/bin/bash
tot=$(wc -c /proc/$$/fd/255 | awk '/ /{print $1}')
now() {
echo $(( 100* ($(awk '/^pos:/{print $2}' < /proc/$$/fdinfo/255)-166) / (tot-166) )) "%"
}
now;
now;
now;
now;
now;
now;
now;
now;
now;

산출:

0 %
12 %
25 %
37 %
50 %
62 %
75 %
87 %
100 %

참고 : 255 대신 1을 입력하면 표준 입력을 모니터링하고 2를 표준 출력으로 모니터링합니다 (그러나 소스를 수정하여 "tot"를 투영 된 출력 파일 크기로 설정해야 함)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.