কীভাবে একটি শেল স্ক্রিপ্টে অগ্রগতি বার যুক্ত করবেন?


413

* NIX এ ব্যাশ বা অন্য কোনও শেল স্ক্রিপ্ট করার সময়, কয়েক সেকেন্ডেরও বেশি সময় নেবে এমন একটি কমান্ড চালানোর সময়, একটি অগ্রগতি বারের প্রয়োজন হয়।

উদাহরণস্বরূপ, একটি বড় ফাইল অনুলিপি করা, একটি বড় টার ফাইল খুলুন।

শেল স্ক্রিপ্টগুলিতে আপনি কোন উপায়ে অগ্রগতি বার যুক্ত করার পরামর্শ দিচ্ছেন?


নিয়ন্ত্রণ যুক্তি ( উদাহরণস্বরূপ একটি কাজের পটভূমি এবং এটি শেষ না হওয়া পর্যন্ত কিছু করুন) এর জন্য উদাহরণস্বরূপ স্ট্যাকওভারফ্লো.com/ প্রশ্নগুলি / 12498304/… দেখুন ।
ট্রিপলি

1
স্ক্রিপ্ট করার সময় প্রয়োজনীয়তার একটি সেট আমরা প্রায়শই দরকারী মনে করি। লগিং, অগ্রগতি, রঙ, অভিনব ফলাফলগুলি প্রদর্শন করা ইত্যাদি ... আমি সবসময় অনুভব করেছি যে কোনওরকম সরল স্ক্রিপ্টিং ফ্রেমওয়ার্ক থাকতে হবে। অবশেষে আমি একটি বাস্তবায়ন করার সিদ্ধান্ত নিয়েছি যেহেতু আমি কোনও খুঁজে পাইনি। আপনি এটি সহায়ক হতে পারে। এটি খাঁটি বাশ, মানে জাস্ট বাশ। github.com/SumuduLansakara/JustBash
সুমাদু

এটি কি unix.stackexchange.com এ স্থানান্তরিত করা উচিত নয় ?
ইথান

উত্তর:


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'

নীচে একটি মন্তব্যে, পুক এই "ব্যর্থতা" উল্লেখ করেছে যদি আপনি একটি দীর্ঘ রেখা দিয়ে শুরু করেন এবং একটি সংক্ষিপ্ত রেখা লিখতে চান: এই ক্ষেত্রে আপনাকে লম্বা রেখার দৈর্ঘ্য (যেমন, স্পেস সহ) লিখতে হবে।


23
ইকো ম্যান পৃষ্ঠা অনুসারে (কমপক্ষে ম্যাকোস এক্স-তে) শ / বাশ তাদের নিজস্ব বিল্ট-ইন ইকো কমান্ড ব্যবহার করবে যা "-n" গ্রহণ করে না ... সুতরাং একই জিনিসটি সম্পাদন করার জন্য আপনাকে put r রাখতে হবে \ গ পংক্তির শেষে, পরিবর্তে শুধু পান \ r
জাস্টিন জেনকিন্স

51
এটির আউটপুট করার পোর্টেবল printfউপায়টি এর পরিবর্তে ব্যবহার করা echo
জেনস

9
প্রিন্টফের জন্য আমাদের এই ফর্ম্যাটটি ব্যবহার করতে হবে:, printf "#### (50%%)\r"এটি একক উদ্ধৃতি দিয়ে কাজ করবে না এবং শতাংশ চিহ্ন এড়াতে হবে।
নুরেটিন

7
আমি এটি পাই না - গৃহীত হয়েছে এবং একটি "আমি অনুমান করতে পারি যে এই অপারেশনটি অজানা হার্ডওয়্যারটির জন্য কতক্ষণ সময় নেবে" হ্যাক হ'ল? পিভি হ'ল সঠিক উত্তর আইএমও (তবে বারটিও করবে)
স্টিফেন

19
ফাইলটি অনুলিপি করার উদাহরণ সহ প্রশ্নটি ছিল "আমি কীভাবে অগ্রগতি বার করব"। আমি "গ্রাফিক্স" সমস্যার দিকে মনোনিবেশ করেছি, ফাইল অনুলিপি অপারেশনটি কতটা দূরে রয়েছে তার গণনা নয়।
মিচ হাইল

73

আপনি কোনও স্পিনার কীভাবে করবেন সে সম্পর্কেও আগ্রহী :

আমি কি ব্যাশে স্পিনার করতে পারি?

নিশ্চিত!

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

প্রতিবার লুপটি পুনরায় পুনরুক্ত হয়, এটি স্প্র স্ট্রিংয়ের পরবর্তী অক্ষরটি প্রদর্শন করে, শেষের দিকে পৌঁছানোর সাথে সাথে মোড়ানো। (আমি প্রদর্শনের জন্য বর্তমান চরিত্রের অবস্থান এবং sp {# এসপি। এসপি স্ট্রিংয়ের দৈর্ঘ্য)।

\ B স্ট্রিংটি একটি 'ব্যাকস্পেস' অক্ষর দ্বারা প্রতিস্থাপিত হয়। বিকল্পভাবে, আপনি লাইনের শুরুতে ফিরে যেতে \ r নিয়ে খেলতে পারেন।

আপনি যদি এটি ধীর করতে চান তবে লুপের ভিতরে একটি স্লাইড কমান্ড দিন (প্রিন্টফের পরে)।

একটি পসিক্স সমতুল্য হ'ল:

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দশমিকের চেয়ে অন্তরালের প্রয়োজন হতে পারে)
অ্যাডাম কাটজ

1
@Daenyth। ধন্যবাদ। দয়া করে আমাদের কমান্ডটি কল করা উচিত যেখানে এটি দেখার দরকার আমাদের আগের কোডটি ব্যবহার করে অগ্রগতি হয়?
গোরো

@ গোরো: some_work ...উপরের লাইনে; একটি আরও বিশদ আলোচনা যা এই সহায়ক উত্তরের উপর ভিত্তি করে এবং অ্যাডাম কাটজের সহায়ক মন্তব্য - পসিক্স সম্মতিতে ফোকাস সহ এখানে পাওয়া যাবে
mklement0

@ অ্যাডাম ক্যাটজ: এটি একটি সহায়ক, বহনযোগ্য সরলকরণ, তবে ডেনিথের পদ্ধতির সাথে মিল রাখতে স্পিনারকে \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
অনাকাঙ্ক্ষিত

1
@ কেউশাল - সিটিআরএল + সি এটি ম্যানুয়ালি বন্ধ করবে। যদি আপনার পটভূমি কাজ থাকে তবে আপনি এর পিআইডি ( 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
অ্যাডাম কাটজ

48

কিছু পোস্ট কীভাবে কমান্ডের অগ্রগতি প্রদর্শিত হবে তা দেখিয়েছে। এটি গণনা করার জন্য, আপনি কতটা অগ্রগতি করেছেন তা আপনাকে দেখতে হবে। বিএসডি সিস্টেমে কিছু কমান্ড, যেমন ডিডি (1) একটি SIGINFOসংকেত গ্রহণ করে এবং তাদের অগ্রগতির প্রতিবেদন করবে। লিনাক্স সিস্টেমে কিছু কমান্ড একইভাবে প্রতিক্রিয়া জানায় SIGUSR1। এই সুবিধাটি উপলভ্য থাকলে, ddপ্রক্রিয়াজাত বাইটের সংখ্যা নিরীক্ষণের জন্য আপনি নিজের ইনপুটটি পাইপ করতে পারেন ।

বিকল্পভাবে, আপনি lsofফাইলের পঠন পয়েন্টার অফসেট পেতে ব্যবহার করতে পারেন , এবং এর মাধ্যমে অগ্রগতি গণনা করতে পারেন। আমি পমনিটর নামে একটি কমান্ড লিখেছি যা একটি নির্দিষ্ট প্রক্রিয়া বা ফাইল প্রক্রিয়াজাতকরণের অগ্রগতি প্রদর্শন করে। এটির সাহায্যে আপনি নীচের মতো জিনিসগুলি করতে পারেন।

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

লিনাক্স এবং ফ্রিবিএসডি শেল স্ক্রিপ্টগুলির পূর্ববর্তী সংস্করণটি আমার ব্লগে উপস্থিত হয় ।


এই সন্ত্রস্ত, আমি সবসময় PV মাধ্যমে পাইপ জিনিষ করতে ভুলবেন :-) আমি আমার "পরিসংখ্যান" কমান্ড একটি বিট ভিন্নভাবে আমার (লিনাক্সের) এই স্ক্রিপ্টের সংস্করণ কাজ করে, মনে হয়: gist.github.com/unhammer/b0ab6a6aa8e1eeaf236b
unhammer

দুর্দান্ত পোস্ট, awkখেলাতে নামার সময় সর্বদা এটি পছন্দ করুন !
শেলফিশ

এটা অসাধারণ! দুর্দান্ত স্ক্রিপ্টের জন্য ধন্যবাদ!
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 এর মধ্যে লাইনটি ব্যাখ্যা করতে পারেন? আপনি কি _ ভরাট এবং _empty ভেরিয়েবলের সাথে একটি শিষ্টা প্রতিস্থাপন করছেন? আমি বিভ্রান্ত
চিরাগ

সেড ব্যবহার করার পরিবর্তে, আমি ব্যাশের অভ্যন্তরীণ "সাবস্ট্রিং রিপ্লেসমেন্ট" ব্যবহার করছি, যেহেতু এটি একটি সহজ কাজ তাই আমি এই জাতীয় কাজের জন্য ব্যাশের অভ্যন্তরীণ ফাংশনগুলি ব্যবহার করতে পছন্দ করি। কোডটি আরও সুন্দর দেখায়। :-) এখানে দেখুন tldp.org/LDP/abs/html/string-manipulation.html এবং স্ট্রিং প্রতিস্থাপনের জন্য অনুসন্ধান করুন।
16

এবং $ {_ পূরণ} স্পেস সংখ্যা $ {_ সম্পন্ন as হিসাবে নির্ধারিত হয়। এটা সুন্দর. দুর্দান্ত চাকরির মানুষ। আমি অবশ্যই এটি আমার সমস্ত বাশ স্ক্রিপ্টগুলিতে ব্যবহার করতে যাচ্ছি
চিরাগ

প্রিয় কাজ @ প্রিয়! গতি উন্নত করার জন্য _ প্রচার যখন শেষ মান থেকে পরিবর্তন না হয় আমি এড়াতে কিছুটা ঝাঁকুনি দিয়েছিলাম। github.com/enobufs/bash-tools/blob/master/bin/progbar
enobufs

মিষ্টি। আয়তক্ষেত্রের সাহায্যে ড্যাশ পরিবর্তন করা এটিকে আরও পেশাদার চেহারা এবং অনুভূতি দেয়:printf "\rProgress : [${_fill// /▇}${_empty// / }] ${_progress}%%"
মেহেদী লামরানী

44

লিনাক্স কমান্ড পিভি ব্যবহার করুন:

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

এটি প্রবাহের মাঝখানে থাকলে আকারটি জানে না তবে এটি একটি গতি এবং মোট দেয় এবং সেখান থেকে আপনি বুঝতে পারেন যে এটি কতক্ষণ নিতে হবে এবং প্রতিক্রিয়া পেতে পারে যাতে আপনি জানেন যে এটি ঝুলেনি।


31

আমি নির্বাচিত উত্তরের চেয়ে আরও সেক্সি কিছু খুঁজছিলাম, তাই আমার নিজের স্ক্রিপ্টটিও ছিল।

পূর্বরূপ

ক্রিয়াকলাপে অগ্রগতি বার

সূত্র

আমি গিথুব এ রেখেছি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
আমি বুঝতে পারি না যে এটি কীভাবে এমন কিছু প্রক্রিয়াজাতকরণের সাথে সংহত করা হয়েছে যেখানে প্রক্রিয়াটির দৈর্ঘ্য জানা যায় না। আমার প্রক্রিয়াটি আগে শেষ হলে কীভাবে অগ্রগতি বারটি থামানো যায়, যেমন কোনও ফাইল আনজিপ করার জন্য ipping
জানু

আমি মনে করি ব্যবহারটি হওয়া উচিতprogress-bar 100
জিরেরিয়াম

আকর্ষণীয় অগ্রগতি সত্যই। এটি কীভাবে এমন কোনও ফাংশনটির সাথে বাঁধা যেতে পারে যা ssh এর মাধ্যমে দূরবর্তী সার্ভারগুলিতে দীর্ঘায়িত ক্রিয়া প্রক্রিয়াকরণ করে? আমি বোঝাতে চাইছি কীভাবে দূরবর্তী সার্ভারগুলিতে একটি আপগ্রেডের সময় (উদাহরণস্বরূপ) পরিমাপ করা সম্ভব?
অবিরাম

1
@ নির্বিঘ্নে আপনি এই সময়টি সরবরাহ করেন এবং এটি গণনা করেন
এডওয়ার্ড লোপেজ

1
@ ফিউশন এটি একটি ইউনিকোড চরিত্র (ইউ + 2587 নীচে সাতটি আট নম্বর) যা আধুনিক শেলের জন্য নিরাপদ হওয়া উচিত। এটিকে আপনার sভুদিবাসীদের চেষ্টা করে দেখুন
লোপেজ

18

জিএনইউ টারের একটি দরকারী বিকল্প রয়েছে যা একটি সাধারণ অগ্রগতি বারের কার্যকারিতা দেয়।

(...) আর একটি উপলভ্য চেকপয়েন্ট ক্রিয়া হ'ল 'ডট' (বা '।')। এটি স্ট্যান্ডার্ড তালিকা প্রবাহে একক বিন্দু মুদ্রণের জন্য টারকে নির্দেশ দেয়, যেমন:

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

একই প্রভাব প্রাপ্ত হতে পারে:

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

সহজ পদ্ধতির জন্য +1! যদি আপনি কোনও বিন্দু মুদ্রিত না দেখেন তবে উদাহরণটি হ্রাস করার চেষ্টা করুন --checkpoint=.10। এটি নিষ্কাশন করার সময় এটি দুর্দান্ত কাজ করে tar -xz
নোয়াম মানস

13

পাইপভিউ (পিভি) ইউটিলিটিটি ব্যবহার করে একটি সহজ পদ্ধতি যা আমার সিস্টেমে কাজ করে।

srcdir=$1
outfile=$2


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

13

অনুরূপ কিছু দেখা যায় নি এবং এখানে সমস্ত কাস্টম ফাংশন একাই রেন্ডারিংয়ে ফোকাস করছে বলে মনে হচ্ছে ... নীচে আমার খুব সাধারণ পসিক্স অনুগত সমাধানটি ধাপে ধাপে ব্যাখ্যা সহকারে এই প্রশ্নটি তুচ্ছ নয়।

টি এল; ডিআর

অগ্রগতি বারটি সরবরাহ করা খুব সহজ। এর কতটা রেন্ডার করা উচিত তা অনুমান করা ভিন্ন বিষয়। অগ্রগতি বারটি কীভাবে রেন্ডার (অ্যানিমেট করা যায়) - আপনি কোনও ফাইলের মধ্যে এই উদাহরণটি অনুলিপি করে আটকে দিতে পারেন:

#!/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 - নীচ থেকে 1 লাইন দিয়ে কাজ করুন
  • tr -s ' ' - একাধিক স্পেস অনুবাদ করুন (সেগুলি বার করুন)
  • cut -d' ' -f3 - তৃতীয় স্পেস-সীমাবদ্ধ কলাম কাটুন

যদিও সমস্যার মাংস এখানে। এই দ্রবণটি কম এবং কম সাধারণ। প্রকৃত অগ্রগতির সমস্ত গণনা আপনি যে ডোমেনটি ভিজ্যুয়ালাইজ করার চেষ্টা করছেন তার সাথে দৃ bound়ভাবে আবদ্ধ, এটি কি কোনও একক ফাইল অপারেশন, টাইমার কাউন্টডাউন, ডিরেক্টরিতে ফাইলের সংখ্যা বৃদ্ধি, একাধিক ফাইলের ক্রিয়াকলাপ ইত্যাদি, তাই, এটি পুনরায় ব্যবহার করা যাবে না। একমাত্র পুনরায় ব্যবহারযোগ্য অংশটি অগ্রগতি বার রেন্ডারিং। এটির পুনঃব্যবহার করতে আপনাকে এটিকে বিমূর্ত করতে হবে এবং একটি ফাইল (যেমন /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
যারা সহজ সরল জিনিস চান তাদের জন্য আমি স্রেফ প্রথম উত্তর দিয়ে আমার তৈরি করেছি mine এটি একটি ফাংশনটির খুব সাধারণ অগ্রগতি বার যা বারটি আঁকতে কিছু বোকা অনুপাতের নিয়ম ব্যবহার করে: পেস্টবিন.
com


9

এপিটি শৈলীর অগ্রগতি বার (সাধারণ আউটপুটটি ভাঙবে না)

এখানে চিত্র বর্ণনা লিখুন

সম্পাদনা: একটি আপডেট সংস্করণ জন্য আমার গিথব পৃষ্ঠা পরীক্ষা করুন

আমি এই প্রশ্নের প্রতিক্রিয়া সন্তুষ্ট ছিল না। আমি ব্যক্তিগতভাবে যা খুঁজছিলাম তা ছিল অভিনব অগ্রগতি বার যা এপিটি দেখেছে।

আমি এপিটি-র জন্য সি উত্স কোডটি দেখেছি এবং বাশের জন্য আমার নিজের সমতুল্য লেখার সিদ্ধান্ত নিয়েছি।

এই অগ্রগতি বারটি টার্মিনালের নীচে সুন্দরভাবে থাকবে এবং টার্মিনালে প্রেরিত কোনও আউটপুটে হস্তক্ষেপ করবে না।

দয়া করে মনে রাখবেন যে বারটি বর্তমানে 100 টি অক্ষর প্রস্থে স্থির করা হয়েছে। আপনি যদি এটি টার্মিনালের আকারে স্কেল করতে চান তবে এটি সম্পন্ন করা মোটামুটি সহজ (আমার গিথুব পৃষ্ঠায় আপডেট হওয়া সংস্করণ এটি ভালভাবে পরিচালনা করে)।

আমি আমার স্ক্রিপ্ট এখানে পোস্ট করব। ব্যবহারের উদাহরণ:

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

স্ক্রিপ্ট (পরিবর্তে আমি দৃ g়ভাবে আমার গিথুবের সংস্করণটি সুপারিশ করছি):

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

এটি এমন একটি অসীম লুপ তৈরি করবে যা পটভূমিতে কার্যকর হয় এবং একটি "প্রতিধ্বনিত হয়।" প্রতি মুহূর্ত. এটি .শেলের মধ্যে প্রদর্শিত হবে । tarকমান্ড বা যে কোনও আদেশ আপনি চান চালনা করুন । যখন এই কমান্ডটি সম্পাদন শেষ করে, তখন পটভূমিতে চলমান শেষ কাজটি মেরে ফেলুন - যা লুপ করার সময় অসীম


মৃত্যুদন্ড কার্যকর করার সময় অন্য কোনও কাজ পটভূমিতে আরম্ভ না করে এবং অগ্রগতির লুপের পরিবর্তে মারা যেতে পারে?
সেন্টটিমান

আমি মনে করি ধারণাটি হ'ল আপনি এটি কোনও স্ক্রিপ্টে রাখবেন, সুতরাং এটি কেবল সেই স্ক্রিপ্টের একটি প্রস্থান ফাঁদে ফেলবে।
ইগুয়ানানাট

1
আমি এই আদেশটি পছন্দ করি, আমি এটি আমার ফাইলগুলিতে ব্যবহার করছি। আমি সত্যিই বুঝতে পারি না যে এটি কীভাবে কাজ করে। প্রথম এবং তৃতীয় লাইনগুলি বোঝা সহজ, তবে আমি এখনও নিশ্চিত নই। আমি জানি এটি একটি পুরানো উত্তর, তবে প্রোগ্রামিংয়ের সময় নবাবিদের প্রতি আমি আলাদা ব্যাখ্যা পেতে পারি এমন কোনও উপায় আছে
ফিলিপ

1
এটি কেবলমাত্র সত্যিকারের উত্তর, যেখানে অন্যরা কেবল 101 টি খেলনা অগ্রগতি বারের স্ক্রিপ্ট করছে যা বাস্তব এবং এক-অফ, অবিরতযোগ্য (প্রায় সব) প্রোগ্রামগুলির জন্য কোনও ব্যবহার নয়। ধন্যবাদ.
বেকস

@ ফিলিপ, দ্য লুপটি একটি পটভূমি প্রক্রিয়া। $! প্রথম ট্র্যাপে সেই ব্যাকগ্রাউন্ড প্রক্রিয়াটির প্রসেস আইডি ক্যাপচার করে এবং নিশ্চিত করে যে বর্তমান / পিতামাতার প্রক্রিয়াটি যদি ব্যাকগ্রাউন্ড প্রক্রিয়াটি শেষ করে তবে এটি মারা যায় এবং এটি ঝুলন্ত অবস্থায় রাখেনি। যখন আপনার দীর্ঘ কমান্ড বা আদেশগুলি শেষ হয় তখন কিল স্টেটমেন্টটি পটভূমি প্রক্রিয়াটি শেষ করে।
ফ্লয়েডন

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"
}

ব্যবহারের উদাহরণ

এখানে, আমরা একটি ফাইল আপলোড করি এবং প্রতিটি পুনরাবৃত্তিতে অগ্রগতি বারটি আবার অঙ্কিত করি। যতক্ষণ না আমরা 2 টি মান পেতে পারি যতক্ষণ বাস্তবে কোন কাজ সম্পাদিত হয় তা বিবেচ্য নয়: সর্বাধিক মান এবং বর্তমান মান।

নীচে উদাহরণে সর্বাধিক মান হয় 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"

ঝরঝরে এবং সহজ ফাংশন। অনেক ধন্যবাদ!
Andreas Kraft

এটিই আমি সন্ধান করছি! অনেক অনেক ধন্যবাদ :)
ওয়াজদী_জুরি

4

বেশিরভাগ ইউনিক্স কমান্ডগুলি আপনাকে যেভাবে সরাসরি এটি করতে পারে তার মত প্রতিক্রিয়া দেয় না। কেউ কেউ আপনাকে ব্যবহার করতে পারেন এমন স্টাডাউট বা স্ট্যাডারকে আউটপুট দেবে।

টারের মতো কোনও কিছুর জন্য আপনি -v স্যুইচটি ব্যবহার করতে পারেন এবং আউটপুটটিকে এমন কোনও প্রোগ্রামে পাইপ করতে পারেন যা এটি পড়ার প্রতিটি লাইনের জন্য একটি ছোট অ্যানিমেশন আপডেট করে। যেমন ট্যার ফাইলগুলি তালিকাভুক্ত করে এটি আনারভেলড করা হয়েছে প্রোগ্রামটি অ্যানিমেশনটি আপডেট করতে পারে। এক শতাংশ সম্পূর্ণ করতে আপনাকে ফাইলের সংখ্যা জানতে হবে এবং লাইনগুলি গণনা করতে হবে।

সিপি এই ধরণের আউটপুট দেয় না যতটা আমি জানি। সিপির অগ্রগতি পর্যবেক্ষণ করতে আপনাকে উত্স এবং গন্তব্য ফাইলগুলি পর্যবেক্ষণ করতে হবে এবং গন্তব্যের আকারটি দেখতে হবে। আপনি ফাইলের আকার পেতে স্ট্যাট (2) সিস্টেম কল ব্যবহার করে একটি ছোট সি প্রোগ্রাম লিখতে পারেন । এটি উত্সের আকারটি পড়তে পারে এবং তারপরে গন্তব্য ফাইলটি পোল করে এবং তারিখটিতে লিখিত ফাইলের আকারের উপর ভিত্তি করে একটি% সম্পূর্ণ বার আপডেট করে।


4

আমার সমাধানটি বর্তমানে টারবলের শতকরা পরিমাণটি প্রদর্শন করে যা বর্তমানে সঙ্কুচিত এবং লিখিত হচ্ছে। 2 জিবি রুট ফাইল সিস্টেমের চিত্রগুলি লেখার সময় আমি এটি ব্যবহার করি। এই জিনিসগুলির জন্য আপনার সত্যিকারের একটি অগ্রগতি বার প্রয়োজন। আমি যা করি তা হ'ল gzip --listটার্বলয়ের মোট অসম্পূর্ণ আকার পেতে। সে থেকে আমি ব্লকিং-ফ্যাক্টরটি গণনা করি যাতে ফাইলটি 100 ভাগে ভাগ করা যায়। অবশেষে, আমি প্রতিটি ব্লকের জন্য একটি চেকপয়েন্ট বার্তা মুদ্রণ করি। 2 জিবি ফাইলের জন্য এটি প্রায় 10 এমবি একটি ব্লক দেয়। যদি এটি খুব বড় হয় তবে আপনি ব্লকিং_ফ্যাক্টরকে 10 বা 100 দ্বারা ভাগ করতে পারেন তবে শতাংশের দিক দিয়ে সুন্দর আউটপুট মুদ্রণ করা আরও শক্ত।

ধরে নিচ্ছি আপনি বাশ ব্যবহার করছেন তবে নীচের শেল ফাংশনটি ব্যবহার করতে পারেন

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}
}

দুর্দান্ত সমাধান তবে আপনি যখন একটি ডিরেক্টরি সংকোচন করতে চান তখন কীভাবে করবেন?
সমীর সাদেক

4

প্রথম বার একমাত্র পাইপ অগ্রগতি মিটার নয়। অন্যটি (সম্ভবত আরও পরিচিত) হলেন পিভি (পাইপ ভিউয়ার)।

দ্বিতীয়ত বার এবং পিভি উদাহরণস্বরূপ ব্যবহার করা যেতে পারে:

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

অথবা এমনকি:

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

আপনি যদি কমান্ডগুলিতে বার এবং পিভি ব্যবহার করতে চান যা আর্গুমেন্টে প্রদত্ত ফাইলগুলির সাথে কাজ করছে যেমন উদাহরণস্বরূপ অনুলিপি ফাইল 1 ফাইল 2, প্রক্রিয়া বিকল্প ব্যবহার করা হয় :

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

প্রক্রিয়া প্রতিস্থাপন একটি বাশ যাদু জিনিস যা এই পাইপটির মাধ্যমে অস্থায়ী ফিফো পাইপ ফাইলগুলি / ডিভ / এফডি / তৈরি করে এবং রানড প্রক্রিয়া থেকে স্ট্যান্ডআউট সংযুক্ত করে (প্রথম বন্ধনীতে) এই অনুলিপিটিকে একটি সাধারণ ফাইলের মতো দেখায় (এক ব্যতিক্রম ব্যতীত, এটি কেবল এটি পড়তে পারে) ফরোয়ার্ড)।

হালনাগাদ:

বার কমান্ড নিজেই অনুলিপি করার অনুমতি দেয়। ম্যান বারের পরে:

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

তবে প্রক্রিয়া প্রতিস্থাপনটি আমার মতে এটি করা আরও সাধারণ উপায়। এটি নিজে সিপি প্রোগ্রাম ব্যবহার করে।


3

আমি - গেজ প্যারামের সাথে ডায়ালগটি ব্যবহার করতে পছন্দ করি । .Deb প্যাকেজ ইনস্টলেশন এবং অনেকগুলি ডিস্ট্রোজের অন্যান্য বেসিক কনফিগারেশনের স্টাটে প্রায়শই ব্যবহৃত হয়। সুতরাং আপনাকে আবার চাকা পুনর্বিবেচনার প্রয়োজন হবে না

1 থেকে 100 @ স্টডিনের জন্য কেবলমাত্র একটি মান লিখুন। একটি মৌলিক এবং নির্বোধ উদাহরণ:

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

রান্নার উদ্দেশ্যে আমার কাছে এই / বিন / ওয়েট ফাইলটি রয়েছে (chmod u + x perms সহ): পি

#!/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?
সিআরপিএন

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। আপনি সম্ভবত এড়াতে চান।
সিআরপিএন

1
@cprn tqdmউপর উন্নতি দেখাব STDERRযখন তার ইনপুট বংশীধ্বনিতুল্য STDINকরতে STDOUT। এই ক্ষেত্রে wc -lযেমন tqdmঅন্তর্ভুক্ত করা হয়নি হিসাবে একই ইনপুট গ্রহণ করুন ।
casper.dcl

আহ, এখন বুঝতে পারি। ব্যাখ্যা করার জন্য ধন্যবাদ।
সিআরপিএন

2

এডুয়ার্ড লোপেজের কাজের উপর ভিত্তি করে, আমি একটি প্রগতি বার তৈরি করেছি যা পর্দার আকারের সাথে মানানসই হোক না কেন, যাই হোক না কেন। এটা দেখ.

এখানে চিত্র বর্ণনা লিখুন

এটি গিট হাব- এও পোস্ট করা হয়েছে ।

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

এটি শুধুমাত্র জিনোম জেনটি ব্যবহার করে প্রযোজ্য। জেনिटी স্ক্রিপ্টগুলিকে বাশ করতে দুর্দান্ত দেশীয় ইন্টারফেস সরবরাহ করে: 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

চর পুনরাবৃত্তি করার জন্য আমি শেল স্ক্রিপ্টে পুনরাবৃত্ত অক্ষরের স্ট্রিং তৈরির একটি উত্তর ব্যবহার করেছি । আমার কাছে স্ক্রিপ্টগুলির জন্য দুটি তুলনামূলকভাবে ছোট বাশ সংস্করণ রয়েছে যার প্রগতি বার প্রদর্শন করা প্রয়োজন (উদাহরণস্বরূপ, একটি লুপ যা অনেকগুলি ফাইলের মধ্য দিয়ে যায় তবে বড় টার ফাইল বা অনুলিপি অপারেশনের জন্য কার্যকর নয়)। দ্রুততমর মধ্যে দুটি ফাংশন থাকে, একটি বার প্রদর্শনের জন্য স্ট্রিং প্রস্তুত করতে:

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

আপনার যদি স্ট্যাডারে প্রগতিবারের প্রয়োজন হয় তবে >&2প্রতিটি প্রিন্টফ কমান্ডের শেষে যুক্ত করুন ।


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;

অগ্রগতির মান / সীমা পরীক্ষা ও প্রদর্শন করতে কেউ লুপের মধ্যে পতাকা / ভেরিয়েবল ব্যবহার করতে পারে ।


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))"
সার্জিও

0

এম্বেড থাকা সিস্টেমের সুযোগ নিয়ে আমি খাঁটি শেল সংস্করণ করেছি:

  • / usr / bin / dd এর SIGUSR1 সিগন্যাল হ্যান্ডলিং বৈশিষ্ট্য।

    মূলত, আপনি যদি একটি 'কিল SIGUSR1 $ (pid_of_running_dd_process)' প্রেরণ করেন তবে তা হ'ল থ্রুপুট গতি এবং স্থানান্তরিত পরিমাণের সংক্ষিপ্তসার আউটপুট করবে।

  • ডিডি ব্যাকগ্রাউন্ডিং এবং তারপরে আপডেটের জন্য নিয়মিত এটি অনুসন্ধান করা এবং পুরাতন স্কুল এফটিপি ক্লায়েন্টের মতো হ্যাশ টিক তৈরি করা।

  • Scp- এর মতো নন-স্টাডাউট বন্ধুত্বপূর্ণ প্রোগ্রামগুলির গন্তব্য হিসাবে / dev / stdout ব্যবহার করা

শেষ ফলাফল আপনাকে যে কোনও ফাইল স্থানান্তর অপারেশন নিতে এবং অগ্রগতি আপডেট পেতে দেয় যা পুরানো-স্কুল এফটিপি 'হ্যাশ' আউটপুট বলে মনে হয় যেখানে আপনি কেবলমাত্র প্রতিটি এক্স বাইটের জন্য একটি হ্যাশ চিহ্ন পাবেন।

এটি উত্পাদন মানের মানের কোড নয়, তবে আপনি ধারণা পাবেন। আমি মনে করি এটি সুন্দর।

এটি মূল্যবান জন্য, আসল বাইট-গণনাটি হ্যাশের সংখ্যায় সঠিকভাবে প্রতিফলিত হতে পারে না - আপনার গোলাকার ইস্যুগুলির উপর নির্ভর করে আরও একটি বা কম থাকতে পারে। এটি কোনও পরীক্ষার স্ক্রিপ্টের অংশ হিসাবে ব্যবহার করবেন না, এটি কেবল চোখের ক্যান্ডি। এবং হ্যাঁ, আমি জানি এটি মারাত্মকভাবে অদক্ষ - এটি একটি শেল স্ক্রিপ্ট এবং আমি এর জন্য ক্ষমা চাইছি না।

উইজেট, স্ক্রিপ এবং টিএফটিপি সহ উদাহরণগুলি শেষে সরবরাহ করা। এটি ডেটা নির্গত করে এমন কোনও কিছু নিয়ে কাজ করা উচিত। স্ট্যান্ডআউট বন্ধুত্বপূর্ণ নয় এমন প্রোগ্রামগুলির জন্য / 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

শালীন ধারণা, যতক্ষণ না আপনার আগে ফাইলের আকার থাকে আপনি পিভি এর চেয়ে অতিরিক্ত মান প্রদান করতে পারেন তবে অন্ধভাবে সংকেত দেওয়া pidof ddভীতিজনক।

'# আমার পিআইডি হ্যান্ডলিং বোবা হচ্ছে'
সিন্থেসাইজারপেটেল

আপনি সম্ভবত $!থেকে ক্যাপচার ddএবং অপেক্ষা করতে পারেন [[ -e /proc/${DD_PID} ]]

0

যদি আপনাকে একটি অস্থায়ী অগ্রগতি বার দেখাতে হয় (প্রদর্শনের সময় আগেই জেনে), আপনি পাইথনটি নিম্নলিখিতভাবে ব্যবহার করতে পারেন:

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

তারপরে, ধরে নিই যে আপনি পাইথন স্ক্রিপ্টটিকে সে হিসাবে সংরক্ষণ করেছেন progressbar.py, নিম্নলিখিত কমান্ডটি চালিয়ে আপনার বাশ স্ক্রিপ্ট থেকে অগ্রগতি বারটি দেখানো সম্ভব:

python progressbar.py 10 50

এটি একটি অগ্রগতি বার আকারের 50অক্ষর এবং 10সেকেন্ডের জন্য "চলমান" দেখায় would


0

আমি ভীত সঞ্চারিত উত্তরটি তৈরি করেছি

এটি একটি আরএমএএন পুনরুদ্ধারের অগ্রগতি পুনরুদ্ধার করতে একটি ওরাকল ডাটাবেসের সাথে সংযোগ স্থাপন করে।

#!/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 ... স্ট্যান্ডার্ড আউট দিয়ে পর্যবেক্ষণ করবেন (তবে আপনাকে উত্পন্ন আউটপুট ফাইলের আকারে "টোট" সেট করতে উত্সটি পরিবর্তন করতে হবে)

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.