gslewis.id.au:~
The Bedlington Ape

Making a copy of Slackware tagfiles

When working with Slackware tagfiles, you generally want to create a copy of just the tagfiles, make your modifications and then direct the installer to use your copy to determine which packages to install. This article looks at the various ways to copy the tagfiles from a local or remote Slackware repository.

Each package set directory in the Slackware repository contains a tagfile. The goal is to copy or download these tagfiles and their parent directories to the chosen local directory.

Slackware x86_64 repository tagfile locations
/path/to/slackware64-current/
  ...
  slackware64/
    a/
      tagfile
    ap/
      tagfile
    d/
      tagfile
    e/
      tagfile
    ...

Rsync

You can use rsync to copy from a local directory source, from a remote source with SSH access, or from a remote rsync server.

The significant rsync arguments are:

--include='tagfile'

Include the tagfile files.

--include='*/'

Include the directory structure.

--exclude='*'

Exclude everything else.

Use the following command if you want to create a copy of the slackware64/ packages directory containing tagfiles. We leave off the trailing slash (/) on SRC so that the slackware64/ directory is what is created at the destination.

Copy Slackware packages directory (slackware64/) with tagfiles
# Note there is no '/' on the end of $SRC
SRC=my_server:/volume1/Public/linux/slackware/slackware64-current/slackware64
DEST=/path/to/destination/

rsync -avm --include='tagfile' --include='*/' --exclude='*' $SRC $DEST

Use the following command if you want to use your own name for the tagfile set directory instead of the repository packages directory name (slackware{64}). In this case we include the trailing slash (/) on the SRC path so that we download the contents of the slackware64/ directory and place the tagfile structure in the my_tagfiles directory.

Copy tagfiles to our own destination directory (my_tagfiles/)
# Note there is a '/' on the end of $SRC
SRC=my_server:/volume1/Public/linux/slackware/slackware64-current/slackware64/
DEST=/path/to/my_tagfiles

rsync -avm --include='tagfile' --include='*/' --exclude='*' $SRC $DEST

Wget

Wget works for both FTP and HTTP(S) using the following options:

-x | --force-directories

Download the tagfile directory structure.

-nH | --no-host-directories

Don’t create a directory for the host server.

--cut-dirs=N

Trim the leading directories so we only get the slackware64/ directory or package set directories.

Execute wget via eval so that the shell expansion of the package sets occurs. For FTP, wget creates a separate FTP connection for each tagfile so it is not very efficient but fine if it is just on a local network. For HTTP, wget reports "Reusing existing connection" for each file.

Download tagfiles using wget
# The list of Slackware package sets.
PKG_SETS="a ap d e f k kde l n t tcl x xap xfce y"

# Convert to a comma-separated string so we can use as a shell expansion.
PKGS=$(echo $PKG_SETS | tr ' ' ',')

# The location of the FTP or web server
SRC=ftp://my_server/Public/linux/slackware/slackware64-current/

# Number of directories to cut.  This depends on the URL path.
# In the case of the above $SRC value:
#   - CUTDIR=4 will download to the slackware64/ directory.
#   - CUTDIR=5 will download to the package set directories (a, ap, d, etc).
CUTDIR=5

# Note ${SRC%/} strips the trailing slash, if any, to ensure we don't get a
double-slash (not that it matters).
eval "wget -x -nH --cut-dirs=$CUTDIR ${SRC%/}/slackware64/{$PKGS}/tagfile"

How do you calculate the --cut-dirs value from the server URL? There are probably a bunch of ways you can do this. The following uses bash pattern-matching operators and awk.

Calculate the wget --cut-dirs value
SRC=ftp://my_server/Public/linux/slackware/slackware64-current/

# Strip the scheme (ftp://, http://, https://)
S=${SRC#*://}
# S=my_server/Public/linux/slackware/slackware64-current/

# Strip the hostname (everything up to and including the first slash)
S=${S#*/}
# S=Public/linux/slackware/slackware64-current/

# Strip the trailing slash if any
S=${S%/}
# S=Public/linux/slackware/slackware64-current

# If we use awk to split $S on slashes and count the number of fields,
# then this is the number of directories to cut to download to the
# slackware64/ directory.
CUTDIR=$(echo $S | awk -F '/' '{ print NF }')
# CUTDIR=4

Curl

Curl works for FTP and HTTP(S) and is somewhat simpler than wget because curl provides its own globbing functionality which lets you define your own directory structure.

# The list of Slackware package sets.
PKG_SETS="a ap d e f k kde l n t tcl x xap xfce y"

# Convert to a comma-separated string so we can use curl's globbing.
PKGS=$(echo $PKG_SETS | tr ' ' ',')

SRC=ftp://my_server/Public/linux/slackware/slackware64-current/

# Don't need to use 'eval' as the '{$PKGS}' glob is handled by curl, not bash.
# Each glob value (a, ap, d, etc) replaces the '#1' placeholder in the output
# path.
curl --create-dirs --output "my_tagfiles/#1/tagfile" ${SRC%/}/slackware64/{$PKGS}/tagfile

Lftp

Lftp works for FTP and HTTP(S) and makes copying the tagfiles simple with the mirror command. It should also work for mirroring local files using the file: scheme. To copy the slackware64 directory structure with the tagfiles only, the following interactive session does the job.

lftp interactive session using mirror command
lftp ftp://my_server
lftp my_server> cd Public/linux/slackware/slackware64-current
lftp my_server> mirror -i tagfile slackware64
lftp my_server> quit

This will copy the slackware64 directory structure to the current local directory with all the package set directories containing the package set’s tagfile only. To copy the tagfiles to a specific local directory, append the destination to the mirror command.

mirror -i tagfile slackware64

Default destination. Tagfiles copied to the local slackware64/ directory.

mirror -i tagfile slackware64 my_tagfiles

Custom destination. Tagfiles copied to the local my_tagfiles/ directory.

To use lftp without the interactive session, we can use the -e option. This runs the commands and does not exit so make the last command "quit" to exit when finished.

lftp -e "mirror -i tagfile slackware64; quit" \
  ftp://my_server/Public/linux/slackware/slackware64-current

Using the -c option also works: it runs the commands and exits. However this option must be used alone so you cannot have the FTP URL at the end. Instead you have to include the "open" command first.

lftp -c "open ftp://my_server/Public/linux/slackware/slackware64-current; \
  mirror -i tagfile slackware64"

Lftp feels considerably slower for FTP than the other methods. However, the mirror command is the simplest to use of all the methods: no globbing, no mixture of obscure wildcard includes and excludes, no having to calculate --cut-dirs values.