Rename directory inside of a tar archive

It shouldn't be very difficult, at least for archives that are compatible with the old-style format where file names are stored in a fixed-size (100 bytes) field, but I don't know of any tool that can rename a file in place in a tar archive. Besides, with a compressed archive, you'd need to create a new file anyway.

It should be even easier, but I don't know of any existing tool that can filter an archive, renaming files as it goes. You can build one on top of tar libraries in scripting languages; for example, here's a proof-of-concept script to rename a directory in a tar archive using Perl with Archive::Tar. The archive is loaded entirely into memory; this is an intrinsic limitation of Archive::Tar.

#!/usr/bin/env perl
## Usage: tar-rename OLDPREFIX NEWPREFIX
use strict;
use warnings;
use Archive::Tar;
my ($from, $to) = @ARGV;
my $tar = Archive::Tar->new(\*STDIN);
foreach my $file ($tar->get_files()) {
    my $name = $file->name;
    $name =~ s~\A\Q$from\E($|/)~$to$1~;
    $file->rename($name) unless $name eq $file->name;
}
$tar->write(\*STDOUT);

GNU tar doesn't have the ability to rename members on the fly, but pax (POSIX's replacement for cpio and tar) does. However, you can't make pax both read and write from an archive. What you can do is expose the archive as a regular tree through AVFS, and create a new archive with pax. This retains file names (except as transformed), contents, times and modes but resets file ownership to you (unless executed as root).

mountavfs
cd "~/.avfs$PWD/old.tgz#"
pax -w -s '!bar!baz!' -s '!bar/!baz/' . | gzip >new.tgz

Both sr_'s hack and Gilles' answer look very good, but if your problem is just the root directory name of the target tarball, while running rpmbuild, a different solution could be to re-define the %setup macro to do the needed dir renaming.

Something like (you'll have to adapt and refine this to your actual configuration, in particular replacing old-dir and desired-dir and using the right decompression tool) this in your ~/.rpmmacros:

%setup cd ../BUILD \
rm -rf cd-player \
bunzip2 -dc ../SOURCES/%{name}-%{version}.tar.bz2 | tar -xvvf - \
if [ $? -ne 0 ]; then \
  exit $? \
fi \
mv <old-dir> <desired-dir> \
cd <desired-dir> \
cd ../BUILD/cd-player \
chmod -R a+rX,g-w,o-w .

I wouldn't honestly do that if not in the most exotic situation, but yours could be the case :)


Just view this page but found the proper answer elsewhere:

http://www.rpm.org/max-rpm/s1-rpm-inside-macros.html

It says that you can pass -n to the %setup macro to tell rpmbuild the name of the top level folder within the tarball

Tags:

Tar