22

I'm writing my own script to download multiple items (simultaneously, one item per command) using wget and I need a progress bar. I currently utilize zenity --progress for my progress bars, but the problem is it spawns multiple progress bars when downloading.

What I want to achieve is something similar to the file transfer dialog in Nautilus:

Ubuntu's file transfer dialog

Can anyone point me to the right direction as to which program(s) or language(s) that will achieve this.

NOTE: I only have basic knowledge of shell scripting, not much else.

Braiam
  • 67,791
  • 32
  • 179
  • 269
Rey Leonard Amorato
  • 2,238
  • 1
  • 16
  • 27

1 Answers1

30

Solution using YAD


Overview

Zenity hasn't been updated in quite a while. Luckily there's a fork called YAD with a lot of added features. It hasn't arrived in the official repositories, yet, but you can install it from a webupd8 PPA:

sudo add-apt-repository ppa:webupd8team/y-ppa-manager
sudo apt-get update
sudo apt-get install yad

One of the features added to YAD is a multi progress-bar dialog. Here's an excerpt from YAD's manual concerning multiple progress bars:

Multi progress bars dialog options
--bar=LABEL[:TYPE]
  Add progress bar. LABEL is a text label for progress bar. TYPE is a progress bar type. Types are:
  NORM for normal progress bar, RTL for inverted progress bar and PULSE for pulsate progress bar.
--vertical
  Set vertical orientation of progress bars.
--align=TYPE
  Set alignment of bar labels. Possible types are left, center or right. Default is left.

Initial values for bars set as extra arguments. Each lines with progress data passed to stdin must be started
from N: where N is a number of progress bar. Rest is the same as in progress dialog.

So a very simple a script with multiple progress bars could look like this:

for i in {1..100}; do
   printf "1:$i\n2:$i\n3:$i\n"
   sleep 0.2
done | yad --multi-progress --bar="Bar 1":NORM --bar="Bar 2":NORM --bar="Bar 3":NORM

This is what the result would look like:

simple yad multi progress script


We can add descriptions to the bars with #:

for i in {1..100}; do
   printf "1:$i\n2:$i\n3:$i\n"
   printf "1:#Progress 1 is at $i percent\n2:#Progress 2 is at $i percent\n3:#Progress 3 is at $i percent\n"
   sleep 0.2
done | yad --multi-progress --bar="Bar 1":NORM --bar="Bar 2":NORM --bar="Bar 3":NORM

Result:

enter image description here


If we want to implement this in a wget download script we will have to do a few things first:

  • find a way to extract the download progress and other interesting data out of the wget output
  • find a way to iterate over multiple files
  • find a way to pass all of the info we have to one single yad dialog

I found this project rather interesting so I sat down and composed a script that should do all of the above.


yad_wget

Here's what I came up with:

#!/bin/bash

# NAME:         yad_wget
# VERSION:      0.2
# AUTHOR:       (c) 2014 Glutanimate
# DESCRIPTION:  graphical frontend to wget in form of a yad script
# FEATURES:     - display progress of multiple simultaneous downloads
#               - set maximum number of simultaneous downloads
# DEPENDENCIES: yad
#
#               Install yad on Ubuntu with:
#
#                   sudo add-apt-repository ppa:webupd8team/y-ppa-manager
#                   sudo apt-get update
#                   sudo apt-get install yad
#
# LICENSE:      GNU GPLv3 (http://www.gnu.de/documents/gpl-3.0.en.html)
#
# NOTICE:       THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 
#               EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 
#               PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR 
#               IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
#               AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND 
#               PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE,
#               YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
#
#               IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY 
#               COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS 
#               PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, 
#               INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE 
#               THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED 
#               INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE 
#               PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER 
#               PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
#
# USAGE:        yad_wget <space-delimited URLs>
#               Closing the yad dialog will terminate all downloads in progress

# Variables and settings

MAXDLS="5" # set maximum number of simultaneous downloads

URILIST="$@" # gets list of URIs from stdin
USAGE="$0 <space-delimited URLs>"

# Set GUI variables up
TITLE="YAD wget downloader"                 # dialog title
TEXT="<b>Downloads</b> in progress:"        # dialog text
ICON="emblem-downloads"                     # window icon (appears in launcher)
IMAGE="browser-download"                    # window image (appears in dialog)

#URILIST="http://proof.ovh.net/files/100Mb.dat http://speedtest.wdc01.softlayer.com/downloads/test10.zip http://cachefly.cachefly.net/100mb.test"

# Usage checks

if [[ -z "$URILIST" ]]
  then
      echo "Error: No arguments provided"
      echo "Usage: $USAGE"
      exit 1
fi


# download file and extract progress, speed and ETA from wget
# we use sed regex for this
# source: http://ubuntuforums.org/showthread.php?t=306515&page=2&p=7455412#post7455412
# modified to work with different locales and decimal point conventions
download(){
    wget  "$1" 2>&1 | sed -u \
    "s/.* \([0-9]\+%\)\ \+\([0-9,.]\+.\) \(.*\)/$2:\1\n$2:# Downloading at \2\/s, ETA \3/"
    RET_WGET="${PIPESTATUS[0]}"             # get return code of wget
    if [[ "$RET_WGET" = 0 ]]                # check return code for errors
      then
          echo "$2:100%"
          echo "$2:#Download completed."
      else
          echo "$2:#Download error."
    fi
}


# compose list of bars for yad
for URI in $URILIST; do                     # iterate through all URIs
    FILENAME="${URI##*/}"                   # extract last field of URI as filename
    YADBARS="$YADBARS --bar=$FILENAME:NORM" # add filename to the list of URIs
done

IFS=" "
COUNTER="1"
DYNAMIC_COUNTER="1"

# main
# iterate through all URIs, download them in the background and 
# pipe all output simultaneously to yad
# source: http://pastebin.com/yBL2wjaY

for URI in $URILIST; do
    if [[ "$DYNAMIC_COUNTER" = "$MAXDLS" ]] # only download n files at a time
      then
          download "$URI" "$COUNTER"        # if limit reached wait until wget complete
          DYNAMIC_COUNTER="1"               # before proceeding (by not sending download() to bg)
      else
          download "$URI" "$COUNTER" &      # pass URI and URI number to download()
          DYNAMIC_COUNTER="$[$DYNAMIC_COUNTER+1]"
    fi
    COUNTER="$[$COUNTER+1]"                 # increment counter
done | yad --multi-progress --auto-kill $YADBARS --title "$TITLE" \
--text "$TEXT" --window-icon "$ICON" --image "$IMAGE"

# ↑ launch yad multi progress-bar window

And this is what it looks like:

enter image description here

           enter image description here

Make sure to read through all the comments to find out how the script works and if you have any questions please don't hesitate to ask in the comments below.


Edit:

I added support for setting the maximum number of simultaneous downloads. E.g. for MAXDLS="5":

enter image description here

Glutanimate
  • 21,393
  • This is a very comprehensive and interesting post, and I'm liking what I'm seeing so far. Thanks for taking the time to tinker with this little project of mine. :)

    Q1: What happens to the progress bar of the completed files? Do they stay on the dialog until everything else is done?

    Q2: From what I'm seeing, there is no way to cancel individual operations from the dialog, is there?

    – Rey Leonard Amorato May 11 '14 at 06:32
  • No problem. I enjoyed working on this . 1: Yes, the bar stays in the dialog. The speed/ETA display switches to say "Download completed" or "Download Error" depending on the exit code of wget. Removing a progress bar after launching the dialog is not possible with yad. 2: No, individual operations can't be cancelled. Unfortunately you can't add any controls to a yad progress bar dialog aside from the buttons below (which will always close the dialog when clicked). If that's something you would like to see you could file a feature request. – Glutanimate May 11 '14 at 11:28
  • Thanks for clearing that up. I would like to wait another 6 days before accepting your answer if you don't mind. I'd be more than happy to award you the +100 if there are no more contributions. – Rey Leonard Amorato May 11 '14 at 13:12
  • Sure, no problem. That's what the bounty is for. – Glutanimate May 11 '14 at 13:16
  • Oh, before you go I have another question. If let's say that I'm downloading a lot of files - say around 20, and my script downloads 5 files at a time, I have to launch a new yad process to show the next batch of downloads, right? – Rey Leonard Amorato May 11 '14 at 15:51
  • Yes, once the dialog has been launched you can't change anything about the number of progress bars. – Glutanimate May 11 '14 at 20:01
  • 1
    +1 for yad; it's a great package. Be aware that --notification on yad will not work on Ubuntu 13.04 and later because of bug 1305835 and bug 1119420 (please follow the links and vote for the bugs). – Paddy Landau May 13 '14 at 10:29
  • @PaddyLandau Oh, I didn't know that (still on 12.04). I'll make sure to check the bug reports out when I'm home. – Glutanimate May 13 '14 at 13:21
  • @ReyLeonardAmorato One small update: You can't change the number of progress bars shown at the same time but you can control the number of simultaneous downloads. I updated my script with a setting that controls this. – Glutanimate May 13 '14 at 19:57
  • 2
    To have additional controls, you would need to step up to GtkDialog which lets you do pretty much anything. However, it's a lot more involved. The PuppyLinux community makes extensive use of it. – DocSalvager May 13 '14 at 20:35
  • @DocSalvage Thanks for introducing me to GtkDialog! I will use it for more complicated projects in the future. It's a shame it's not in the official repos, though. I was able to grab a package here for now. – Glutanimate May 13 '14 at 20:57
  • @Glutanimate Great update. Now this does exactly what my old script does, but with the progress bars on one window. Thanks! – Rey Leonard Amorato May 14 '14 at 13:05
  • 1
    @Glutanimate - One brief note to avoid much confusion: Many of the references on PuppyLinux forums refer to "gtkdialog3" and "gtkdialog4". These are just simpler synonyms for the real GtkDialog versions and they're not even consistent. Version 0.8.3 that you grabbed is the latest and is quite stable. ( Moderators: No more on GtkDialog here. Anyone interested in it should please post new questions. ) – DocSalvager May 14 '14 at 18:13
  • @Glutanimate - If you haven't already posted this on the yad list, it's a great example to add. I know I'm going to study it. I've been using yad for a couple of years and love it. The developer is very responsive and helpful too. – Joe May 15 '14 at 03:04
  • @Joe Good idea. Done ☺. – Glutanimate May 16 '14 at 01:48
  • @PaddyLandau Your first bug link has been closed because notification area is no longer supported in Unity.You may wish to delete your comment dated May 13'15 10:29 and post an updated comment. ps I agree yad is a great program and I also +1 this answer (and the question too). – WinEunuuchs2Unix Jul 01 '17 at 17:04
  • 1
    @Glutanimate I've been using yad for a few months now and have been greatly impressed with its power. Your answer here though is absolutely brilliant and light years ahead of my own progress bars. I'll be very quick to adapt your wget progress bar code into my own app: https://askubuntu.com/questions/900319/code-version-control-between-local-files-and-au-answers/900609#900609. – WinEunuuchs2Unix Jul 01 '17 at 17:09
  • Note that as of version 4.0, --multi-progress is merged into --progress: https://github.com/v1cont/yad/blob/1d30e86f92e062cf3f6cfce33e0a52d9414b015c/NEWS#L106 – Zeta.Investigator Apr 20 '22 at 18:24