Топик посвящается тем, кто не любит качать тяжелые файлы браузером из файлообменников, а также для тех кто хочет получше понять работу zenity.

В Linux есть много различных качальщиков от консольных до тяжелых java-приложений и мой скрипт это не еще один новый качальщик, это всего лишь приятная для глаз (eye-candy) обертка для стандартного Wget. Хотя в потенциале он умеет все что умеет Wget, но я реализовал только самые его основные функции. Цель данного скрипта — запустить закачку через wget (отвязав ее от браузера) и показывать ход ее выполнения.

В среде GTK+ есть замечательная утилита Zenity которую я и буду использовать для показа диалоговых окошек. По ссылке достаточно подробно показаны все аспекты использования, поэтому я не буду делать обзор, а сразу покажу как я ее применял.

Итак, в своем скрипте я реализовал минимальный функционал для того чтобы качать с комфортом: лист ссылок, выбор прокси, http, ftp-протоколы, исправление имени закачиваемого файла (очень полезно для роликов с YouTube и ему подобных), работа из командной строки (для работы с плагином Firefox FlashGot).

#!/bin/bash
#Usage: ./guiwget
# with FlashGot arguments are: [URL] [REFERER] [POST]
#Dependens: wget>=1.11.1, zenity

Да-да! Есть разница в версиях wget. В версии 1.11.1 wget стал поддерживать опцию --content-disposition которая необходима при скачивании с обменников, например, ifolder или youtube. Также показаны опции для FlashGot чтобы была возможность скачивать flv-ролики, и передавать закачки wget.
#Get URL
[ "$1" ] && url=$1 || url="$(zenity --text-info --editable --title="Введите список URL" --width=500 --height=300)";
[ "$url" ] || exit 0;


Если ссылка была передана через FlashGot, то праметры обработаются, а если он был запушен напрямую, то выведется окошко с запросом списка URL. Скрипт завершит работу если список закачек пуст.
#Proxy
proxy1="Ангола"; proxy1addr="41.210.252.11:80";
proxy2="Бангладеш"; proxy2addr="202.168.236.178:8080";
p="$(zenity --list --title="Выбор прокси" --print-column=2 --column="" --column="" "$proxy1" "$proxy1addr" "$proxy2" "$proxy2addr")";
[ "$p" = "" ] || proxy="export http_proxy=http://$p";

Работа с прокси, ничего необычного, для примера показаны два прокси. По идее нужно реализовать работу импорта подготовленного списка прокси, но мне это без надобности. Если хотите качать напрямую, жмите кнопку «Отмена» в окошке.
#Folder selection for file downloading
downdir="$(zenity --file-selection --directory --title="Выбор каталога для сохранения")";
[ "$downdir" ] || exit 0;

Выбор папки для скачивания. Можно жестко прописать путь в скрипте, но я люблю разнообразие :)

Настройка параметров окончена, начинается самая основная работа:
for urs in $url
do
    #Log file
    output="/tmp/`date +%N`-log";
    #Wget start
    id=$($proxy; wget -b -o"$output" -P"$downdir" --referer="$2" --post-data="$3" "$urs" | egrep -o "[0-9]+");
    [ "$id" ] || exit 0;

Запускаем wget c полученными параметрами, отправляем в фон, пишем ход скачивания в лог, который и будет обрабатываться, запоминаем id процесса.
    #Name file and size
    h="";
    while [ "$h" == "" ]; do
    if [ -x /proc/$id ]
        then
        h=$(egrep -o "[^\/]+'.$" $output);
        [ "$h" = "" ] && h=$( sed -n '/RETR/s/.*RETR \([[:print:]]*\)… готово.$/\1/p' $output);
        realname="${h%\'.}";
        downfile="${realname%%\?*}";
        [ "$realname" != "$downfile" ] && [ -f "$downdir/$downfile" ] && downfile=`date +%N`"_"$downfile;
        else
        zenity --text-info --title="Ошибка" --filename=$output --width=700 --height=400;
        h="FAIL";
        rm $output;
    fi
    done;
    [ "$h" == "FAIL" ] && continue;
    size=$(grep "Длина:" $output | tail -1 | egrep -o "\(.+\)" | cut -d"(" -f2 | cut -d")" -f1);

Определяем имя файла, размер и вообще убеждаемся что сервер отдает нам файл, если что-то идет не так, показывается окошко с логом, там wget обычно пишет что именно не так. Переменная downfile нужна для того чтобы корректно показывать имя файла, а также для того чтобы превратить имя файла file?var=1&var=2 в file.
Один ньюанс — работа идет с логом на русском языке и перехватываются русские слова, если у вас это не так, поправьте слова «готово» и «Длина» в скрипте на свои.
    #Grafical progressbar
    (tail -f --pid=$id $output | sed -u -n 's/.*\.[ ]*\([[:print:]]*\)%[ ]*\([[:graph:]]*\) \([[:graph:]]*\)$/# '"$downfile"': '$size' \1% [\2Б\/с] (\3)\n\1/p') | zenity --title="Загрузка файла $p" --progress --percentage=0 --auto-close
    [ $? -eq 0 ] && notify-send "Скачивание завершено" "Файл: $downfile" || ( [ -x /proc/$id ] && kill $id || zenity --text-info --title="Ошибка" --filename=$output --width=700 --height=400);
    mv "$downdir/$realname" "$downdir/$downfile";
    #Clean
    rm $output;
done

А здесь и есть моё ноу-хау, рассказываю как это работает.
tail -f --pid идеально подходит для слежения за логом, причем он следит еще и за pid процесса, так что когда процесс с заданным pid завершится, tail тоже остановит работу конвейера. Потоковый tail передает потоковому (в отличии от awk) sed файл лога wget, который обрабатывает его, выцепляя нужную информацию и должным образом ее форматирует, ну и дальше текст приходит в zenity.
Немного поясню, в zenity --progress нужно подавать текст в виде:
# текст для отображения
0
# текст для отображения
10


где вторая строчка это число процентов. Таким преобразованием из лога wget заняты tail+sed. Дальше идет отработка ошибок или вывод всплывающего сообщения если закачка была завершена удачно, также следует переименование файла, если это требуется.

Ну вот и все, сохраняете файл где вам удобно, выставляете бит исполнения, добавляете кнопку запуска на панельку и пользуетесь или через Firefox+FlashGot отправляете задания.

И последний штрих, дабы победить Rapidshare и прочие файлообменники которые не любят перехватчиков ссылок, в файл .wgetrc добавьте такие строчки:
header = Accept-Language: ru,en-us;q=0.7,en;q=0.3
header = Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
header = Accept-Encoding: gzip,deflate
header = Accept-Charset: UTF-8,*
header = Keep-Alive: 300
header = Connection: keep-alive
user_agent = Mozilla/5.0 (X11; U; Linux i686; ru; rv:1.9.1.2) Gecko/20090804 Shiretoko/3.5.2
content_disposition = on

Юзер-агент поправьте в соответствии с вашим браузером.

Скрипт можно взять здесь: nebulosa2007.narod.ru/guiwget.tar.gz