انجمن‌های فارسی اوبونتو

لطفاً به انجمن‌ها وارد شده و یا جهت ورود ثبت‌نام نمائید

لطفاً جهت ورود نام کاربری و رمز عبورتان را وارد نمائید

نویسنده موضوع: اسکریپت برای کپی و نمایش همزمان progress bar (حل شد)  (دفعات بازدید: 2036 بار)

0 کاربر و 1 مهمان درحال مشاهده موضوع.

آفلاین nino

  • Full Member
  • *
  • ارسال: 224
  • جنسیت : پسر
    • Gitlab
سلام.
یک اسکریپت ساده داریم برای کپی فایل، حاوی دو بخش:
اول، فرمان کپی فایل های مورد نظر. مثلا:
دوم: یک progress bar (که در اینجا به شکل یک / چرخانه):
cp -r /home/user/Photos /home/user/Backup

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

مشکل اینجاست که نمی دونم چطور هر دو تا دستور با هم انجام بشه.
یعنی در حین انجام شدن کپی، اون progress bar هم نشون داده بشه و با اتمام کپی قطع بشه، اما الان اینجوریه که کپی باید تموم بشه تا بخش بعدی شروع به کار بکنه.
گزینه دیگه هم اینه که فرمان کپی رو بزارم آخر اسکریپت ولی فرمان progress bar به صورت لوپه و همینطور به چرخیدن ادامه میده.
حتی بین این دو دستور از & هم استفاده کردم تا همزمان انجام بشن اما تاثیری نداشت.
« آخرین ویرایش: 08 شهریور 1397، 12:24 ق‌ظ توسط Nino »
...

آفلاین SMAH1

  • Jr. Member
  • *
  • ارسال: 35
  • جنسیت : پسر
پاسخ : اسکریپت برای کپی و نمایش همزمان progress bar
« پاسخ #1 : 07 شهریور 1397، 03:36 ب‌ظ »
سلام
در برنامه نویسی مفهومی داریم به نام forking که به نظرم باید اینجا استفاده بشه.
دو نمونه لینک می‌آورم ولی باید بیشتر جستجو کنی:
https://unix.stackexchange.com/questions/7608/does-bash-support-forking-similar-to-cs-fork
https://stackoverflow.com/questions/3096561/fork-and-exec-in-bash

آفلاین علی رزم دیده

  • عضو کاربران ایرانی اوبونتو
  • *
  • ارسال: 1244
  • جنسیت : پسر
  • ali76 سابق
پاسخ : اسکریپت برای کپی و نمایش همزمان progress bar
« پاسخ #2 : 07 شهریور 1397، 10:17 ب‌ظ »
سلام

اول یه سری مباحث رو توضیح می دم بعدش می رم سر قسمت اصلی کد :

1.اگه شما دستورات رو به همون صورت که نوشتین (و یا به صورت command 1 ; command 2) اجرا کنین ، این دستورات دقیقاً به همین ترتیبی که نوشته شدن اجرا می شن.
یعنی اول دستور اول اجرا می شه بعدش دستور بعدی و ....


2.چون گفتین بین دستورات && رو گذاشتین ، این رو هم بهتره توضیح بدم :
وقتی از && استفاده می کنیم اینجا هم عین حالت قبل اول دستور اول و بعدش دستور دوم اجرا می شه منتهی تفاوتش اینه که دستور دوم تنها و تنها زمانی اجرا می شه که دستور اول با موفقیت اجرا بشه.


ولی چیزی که شما می خواین این هستش که هر دو دستور همزمان اجرا بشن.
برای اینکار شما باید دستور اول رو به پس زمینه منتقلش کنین تا بلافاصله دستورات بعدی اجرا بشن. (برای اینکار راه های مختلفی مثل استفاده از & و یا nohup وجود داره)

ولی شما یه چیز دیگه ای هم می خواین و اونم اینه که دستور دوم تا زمانی اجرا بشه که دستور اول در حال اجرا هستش.
برای این کار هم راه زیاد داریم ولی یکی از بهترین راه ها اینه که pid مربوط به دستور اول رو توی یه متغیر نیگه داریم و به جای while true (که در واقع حلقه ی بی نهایت هستش) از ساختاری استفاده کنیم که تا زمانی که اون pid موجود هستش دستورات اجرا بشن.

برای این کار می تونین از این اسکریپت استفاده کنیم (من سعی کردم دستوری رو که شما نوشتین رو با کمترین تغییر اصلاح کنم و به ساختارش دست نزنم) :

cp -r /home/user/Photos /home/user/Backup &
pid=$!

i=1
sp="/-\|"
echo -n ' '

while ps -p $pid &>/dev/null ; do
    printf "\b${sp:i++%${#sp}:1}"
done


پ.ن 1: برای اینکار که می خواین انجام بدین ( progress bar در کپی فایل) راه های بهتری هم وجود داره مثلا استفاده از rsync و pv و dd و ...
که می تونین از اونا استفاده کنین.


پ.ن 2:توی حلقه تون حتماً حتماً از sleep استفاده کنین وگرنه اینی که شما نوشتین بار زیادی رو به پردازنده تحمیل می کنه و اینو می تونین از طریق htop موقع اجرای اسکریپت چک کنین.
توصیه ی من چنین ساختاری هستش :
while true ; do
    sleep 0.1s;
    printf "\b${sp:i++%${#sp}:1}"
done

آفلاین Silvio Dante

  • High Hero Member
  • *
  • ارسال: 1221
  • جنسیت : پسر
  • Arch Linux
    • وبلاگ شخصی
پاسخ : اسکریپت برای کپی و نمایش همزمان progress bar
« پاسخ #3 : 07 شهریور 1397، 10:50 ب‌ظ »
توضیحات آقای رزم دیده خیلی خوب و کامل بود.
این اسکریپت هم چیزی بود که من وقتی تاپیک‌تون رو دیدم برام جالب شد ببینم چجوری می‌شه همچین کاری انجام داد که با کمی سرچ توی اینترنت و رسیدن به همین pidای که آقای رزم دیده گفتن، نوشتمش، و همچنین خروجی progress barهم کمی متفاوته (بنظرم این حالت جذاب‌تر بود) که البته می‌تونین مال خودتون رو جایگزین کنین:
#!/bin/bash
cp -a ~/Photos ~/Backup &
pid=$!

trap "kill $pid 2> /dev/null" EXIT
spin[0]="-"
spin[1]="\\"
spin[2]="|"
spin[3]="/"

echo -n "[copying] ${spin[0]}"
while kill -0 $pid 2> /dev/null
do
  for i in "${spin[@]}"
  do
        echo -ne "\b$i"
        sleep 0.1
  done
done

trap - EXIT
به ما نگفته بودند ایران در زمان احمدشاه قاجار چگونه بوده است. همیشه به ما دادند، ما هم فکر کردیم باید می‌داده‌اند و تازه خیال می‌کردیم کم‌مان است باز هم می‌خواستیم!!
فریدون فرخزاد

آفلاین nino

  • Full Member
  • *
  • ارسال: 224
  • جنسیت : پسر
    • Gitlab
پاسخ : اسکریپت برای کپی و نمایش همزمان progress bar
« پاسخ #4 : 07 شهریور 1397، 10:57 ب‌ظ »
برای این کار می تونین از این اسکریپت استفاده کنیم (من سعی کردم دستوری رو که شما نوشتین رو با کمترین تغییر اصلاح کنم و به ساختارش دست نزنم) :

cp -r /home/user/Photos /home/user/Backup &
pid=$!

i=1
sp="/-\|"
echo -n ' '

while ps -p $pid &>/dev/null ; do
    printf "\b${sp:i++%${#sp}:1}"
done
بله این دقیقا چیزیه که مدنظر من بود و به خوبی جواب میده.  =D>
البته این خط رو هم به آخر اسکریپت اضافه کردم که بعد از تموم شدن کار کپی، کاراکترهای خط قبلش رو کامل پاک کنه:
echo -en "\033[1K\r"
پ.ن 1: برای اینکار که می خواین انجام بدین ( progress bar در کپی فایل) راه های بهتری هم وجود داره مثلا استفاده از rsync و pv و dd و ...
که می تونین از اونا استفاده کنین.
pv و bar رو امتحان کردم ولی واسه من کار نمی کردن. pv نوارش ثابت بود و هیچ حرکتی نداشت. فقط تونستم از تایمرش استفاده کنم، که به درد کار من نمی خورد.
rsync و dd رو هم حتما امتحان می کنم. گزینه های خوبین. توی سایت های دیگه هم زیاد پیشنهاد شده بودن.
در مورد sleep هم حق با شماست. باید اضافه بشه.

تشکر بسیار زیاد.
« آخرین ویرایش: 08 شهریور 1397، 12:24 ق‌ظ توسط Nino »
...

آفلاین nino

  • Full Member
  • *
  • ارسال: 224
  • جنسیت : پسر
    • Gitlab
پاسخ : اسکریپت برای کپی و نمایش همزمان progress bar
« پاسخ #5 : 07 شهریور 1397، 11:06 ب‌ظ »
#!/bin/bash
cp -a ~/Photos ~/Backup &
pid=$!

trap "kill $pid 2> /dev/null" EXIT
spin[0]="-"
spin[1]="\\"
spin[2]="|"
spin[3]="/"

echo -n "[copying] ${spin[0]}"
while kill -0 $pid 2> /dev/null
do
  for i in "${spin[@]}"
  do
        echo -ne "\b$i"
        sleep 0.1
  done
done

trap - EXIT
الان اینو هم امتحان کردم ولی واسه من هیچ progress bar نشون نداد.
نیاز به نصب نرم افزار خاصی داره؟!
...

آفلاین Silvio Dante

  • High Hero Member
  • *
  • ارسال: 1221
  • جنسیت : پسر
  • Arch Linux
    • وبلاگ شخصی
پاسخ : اسکریپت برای کپی و نمایش همزمان progress bar
« پاسخ #6 : 08 شهریور 1397، 02:15 ق‌ظ »
الان اینو هم امتحان کردم ولی واسه من هیچ progress bar نشون نداد.
نیاز به نصب نرم افزار خاصی داره؟!
نه نرم افزار خاصی نمی‌خواد. احتمالا فایل‌ها‌تون رو یه بار کپی کردین و دیگه چیزی نبوده کپی کنه. عکس متحرک ضمیمه شده رو نگاه کنین اینجوریه خروجیش.
به ما نگفته بودند ایران در زمان احمدشاه قاجار چگونه بوده است. همیشه به ما دادند، ما هم فکر کردیم باید می‌داده‌اند و تازه خیال می‌کردیم کم‌مان است باز هم می‌خواستیم!!
فریدون فرخزاد

آفلاین nino

  • Full Member
  • *
  • ارسال: 224
  • جنسیت : پسر
    • Gitlab
پاسخ : اسکریپت برای کپی و نمایش همزمان progress bar
« پاسخ #7 : 08 شهریور 1397، 09:27 ق‌ظ »
نه نرم افزار خاصی نمی‌خواد. احتمالا فایل‌ها‌تون رو یه بار کپی کردین و دیگه چیزی نبوده کپی کنه. عکس متحرک ضمیمه شده رو نگاه کنین اینجوریه خروجیش.
آره اینم چرخانه. الان دوباره امتحان کردم درست بود.
اولی به نظر کمی ساده تر نوشته شده. حالا با توجه به این که این دو تا متفاوت از هم نوشته شدن، شما کدوم رو پیشنهاد می دید؟
...

آفلاین Silvio Dante

  • High Hero Member
  • *
  • ارسال: 1221
  • جنسیت : پسر
  • Arch Linux
    • وبلاگ شخصی
پاسخ : اسکریپت برای کپی و نمایش همزمان progress bar
« پاسخ #8 : 08 شهریور 1397، 02:15 ب‌ظ »
آره اینم چرخانه. الان دوباره امتحان کردم درست بود.
اولی به نظر کمی ساده تر نوشته شده. حالا با توجه به این که این دو تا متفاوت از هم نوشته شدن، شما کدوم رو پیشنهاد می دید؟
فرق خاصی ندارن هر دو یک کار یکسان رو انجام می‌دن فقط اونی که من نوشتم ظاهر خروجی‌ش تفاوت داره. از ظاهر هر کدوم که خوشتون میاد استفاده کنین.
به ما نگفته بودند ایران در زمان احمدشاه قاجار چگونه بوده است. همیشه به ما دادند، ما هم فکر کردیم باید می‌داده‌اند و تازه خیال می‌کردیم کم‌مان است باز هم می‌خواستیم!!
فریدون فرخزاد