4

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!

  • 2
    Could you clarify what you mean by "dget doesn't have any option to specify a different repository URL"? It takes the URL on the command line... Or does apt-get --download-only install provide what you're after? – Stephen Kitt Aug 10 '16 at 8:08
  • @StephenKitt The URL option of the dget specifies a package URL, and not a repository URL. I want to download packages from a remote repo 1) automatized 2) without modifying my /etc/apt/sources.list . But, I don't know the exact URLs of the packages, I know only their name and the exact URL of their repo. | apt-get would also download dependencies, and has a complex configuration. I don't need these. – peterh - Reinstate Monica Aug 10 '16 at 8:17
  • Could you translate “the script-solutions also get now an up, but not a pipe” into English? What does this question have to do with pipes? – Gilles 'SO- stop being evil' Aug 10 '16 at 22:58
  • Are you going to run this on a Debian (or Debian-based) system, or are you looking for something that can be deployed on any unix-like system? – Gilles 'SO- stop being evil' Aug 10 '16 at 22:59
  • @Gilles Well, "pipe" has different meanings in Unix and in SE context :-) I "translated". – peterh - Reinstate Monica Aug 10 '16 at 23:01
3
+50

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.

| improve this answer | |
9

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

| improve this answer | |
  • Finally I solved with dget, although I wasn't happy to modify the system-wide repos. But, thank you very much script! – peterh - Reinstate Monica Aug 11 '16 at 15:31
  • @peterh could you post the solution you actually used as an answer, instead of leaving everyone guessing? Thanks! – Stephen Kitt Aug 11 '16 at 16:37
2

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.

| improve this answer | |
  • Repos are static file repositories with static file indices, whose primary function is to find the package URL based on its name (and other metadata, like version, distrib codename, etc). This is exactly what I wish. What I do with the downloaded packages, isn't a business of the repo. It only provides packages. Writing a script for that seems impractical, while the required functionality is already available in many debian tools, although it could be acceptable if there is no better. – peterh - Reinstate Monica Aug 10 '16 at 9:25
  • @peterh In that case I'd suggest you'd simply get the rest of the information from uname and assemble the information. As I understand it, you want to provide a repo baseurl manually via cli an the client tool would search for a package inside of it? if so, I don't think there's an apt-cache search tool for cli repos available. – polemon Aug 10 '16 at 9:44
  • apt-cache uses the systemwide apt package cache, and I've already explained why I won't use the systemwide apt cache. It would be like shooting with cannon to a fly. – peterh - Reinstate Monica Aug 10 '16 at 9:54
  • uname can say at most the architecture. The exact URL can be found only in the package index of the repository. My main prolem with the debian that finding the correct tool for a simple task is often harder as reimplement it with a little bit of scripting. – peterh - Reinstate Monica Aug 10 '16 at 10:01
2

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

| improve this answer | |
  • I am looking for mainly a "clean" debian thing, my solution will be part of build scripts where unneeded complexity has high collateral costs. But, if there is no better solution for that, it will be acceptable. (Again: I don't need to install the package, and particularly not its repositories, I only want to download it. Thus, the apt install thing is not really needed at the end of your script, but it will be easy to change to dget.) – peterh - Reinstate Monica Aug 10 '16 at 8:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.