How to download packages from a command-line given repository?

It is not about the common download & install thing, what apt (aptitude, etc) does, it is a scripted download a package file.

I found the dget tool for this task, which works quite well. But, unfortunately, it doesn’t have any option to specify a different repository URL as it is given in the /etc/apt/sources.list.

Is it somehow possible? Actually, a dget-like functionality would be the best, but where I can also specify the repo URL.


P.s. thank you very much the scripts, but I would like to prefer a debian tool for this very simple task. It will be part of a buildscript, for external usage, and any unneeded complexity has intolerable collateral costs. It must be done by a debian tool.

P.s.2. Finally I solved this with updating the system-wide repos, and downloading the packages with dget. Thank you very much the scripts!

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

All the tools I can find use the local apt information (and hence repositories in /etc/apt/sources.list etc., as defined the last time apt-get update was run). It’s not too difficult to interpret the repository format though.

Save

#!/bin/sh
# Downloads a package from a repository
# dlpkg repo distro suite arch package

for arch in all "${4}"; do
    curl "${1}/dists/${2}/${3}/binary-${arch}/Packages.xz" | xz -d | "$(dirname $0)/pkgfilename" -v "PACKAGE=${5}" | while read filename; do
        curl -O "${1}/${filename}"
    done
done

as dlpkg, and

#!/usr/bin/awk -f

/Package:/ {
    package = $2
}

package == PACKAGE && /Filename:/ {
    print $2
}

as pkgfilename, make them executable, and you can then download a package by running

./dlpkg <repository URL> <distribution> <suite> <architecture> <package>

for example

./dlpkg http://ftp.fr.debian.org/debian unstable main amd64 libc6

If you need to handle repositories whose Packages files aren’t in canonical order (Package before Filename), you can use the following AWK script instead:

#!/usr/bin/awk -f

BEGIN {
    filename = ""
}

/^$/ {
    filename = ""
    stanza = 0
}

/Package:/ {
    if ($2 == PACKAGE) {
        stanza = 1
        if (filename != "") {
            print filename
            stanza = 0
        }
    }
}

/Filename:/ {
    filename = $2
    if (stanza == 1) {
        print filename
        filename = ""
    }
}

There’s no error-handling, that’s left as an exercise for the reader. There’s no signature verification either…

Solution 2

If you’re running a reasonably recent version of Debian or other distribution using apt, you can use apt-get for this. Put the following settings in a file called apt-get.conf to make it not use

Dir::Etc::main ".";
Dir::Etc::Parts "./apt.conf.d";
Dir::Etc::sourcelist "./sources.list";
Dir::Etc::sourceparts "./sources.list.d";
Dir::State "./apt-tmp";
Dir::State::status "./apt-tmp/status";
Dir::Cache "./apt-tmp";

Prepare some necessary files:

mkdir -p apt-tmp/lists/partial
touch apt-tmp/status
apt-get -c apt.conf update >/dev/null

Then you can download packages to the current directory with

apt-get -c apt.conf download $packages

With old versions of apt-get that lack the download command, you can use

apt-get -c apt.conf install -d $packages

to download packages and their dependencies into apt-tmp/archives.

Solution 3

I don’t think what you’re trying to achieve is in line with the idea of having repos as such. The idea being, you’d have to add the repo to the repolist, and then install from it, etc.

It is possible to download a package manually (I do that quite often with RPM packages for Fedora), and install a package manually with the regular tools (in my case dnf).

I usually use the URL from /etc/yum.repos.d/<repo>.repo and then just browse with a browser, and download with wget. It should be analogous with DEB packages.

So,

  1. Download package manually with a browser or wget
  2. Install with your package management client from cli.

If the repo is directly available online (which I don’t see why not), dnf understands when it is given a URL to an RPM package. I’m sure the equivalent Debian tool will do the same. So you’ll save yourself downloading the package with a browser or with wget.

As I understand it, you’r only interested in just downloading the packages. So in that case, I think using plain wget is the best way to go, etc.

Solution 4

Well maybe this script is a solution for your needs:

#!/bin/bash

U="$1"
FILE="$2"

[[ -z "$U" ]] && echo -e "Usage: $0 repo-url [file to download]\nwithout give \"file to download\" this script will list the files inside the repo\n";

for i in $(curl -l "$U" 2>/dev/null|grep -i 'href='|sed -e 's/.*href=//g' -e 's/>.*//g' -e 's/"//g'|grep -v '/$'|grep "$FILE")
do
 if [[ -z "$FILE" ]]
 then
  echo "FILE: $i"
 else
  echo "Download file: $i"
  curl -q "${U}/${i}" --output "$i" 2>/dev/null
  ls -la "$i"
 fi
done

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply