Benennen Sie das Verzeichnis in einem tar-Archiv um

14

Ist es möglich, ein Verzeichnis innerhalb eines tar-Archivs umzubenennen? Mein Anwendungsfall ist, dass ich eine extern bereitgestellte RPM-Spezifikationsdatei habe, die einen Tarball mit einer bestimmten Verzeichnisstruktur annimmt, und ich habe einen extern bereitgestellten Tarball, dessen Verzeichnisname der obersten Ebene nicht mit den Erwartungen der Spezifikationsdatei übereinstimmt. Ich kontrolliere weder das Skript, das die Tarballs generiert, noch die RPM-Spezifikationsdatei, so dass ich keine Änderung vornehmen kann, um sie an die anderen anzupassen.

Was ich getan habe, ist, den Teer zu entfernen, den Verzeichnisnamen zu ändern und dann einen neuen Tarball zu erstellen, aber ich habe mich gefragt, ob es eine Alternative dazu gibt.

Lorin Hochstein
quelle
3
Leider bezweifle ich das, aber es würde mich interessieren, ob jemand anders einen Weg hat. Ich denke, Ihre beste Wahl ist es, ein Skript zu schreiben, mit dem Sie das Teer entfernen, umbenennen und neu tarieren können.
Kevin

Antworten:

8

Zumindest für Archive, die mit dem alten Format kompatibel sind und in denen Dateinamen in einem Feld mit fester Größe (100 Byte) gespeichert sind, sollte es nicht sehr schwierig sein, aber ich kenne kein Tool, das a umbenennen kann Datei an Ort und Stelle in einem Tar-Archiv. Außerdem müssten Sie bei einem komprimierten Archiv ohnehin eine neue Datei erstellen.

Es sollte noch einfacher sein, aber ich kenne kein vorhandenes Tool, mit dem ein Archiv gefiltert und Dateien umbenannt werden können. Sie können eine über tar-Bibliotheken in Skriptsprachen erstellen. Hier ist beispielsweise ein Proof-of-Concept-Skript zum Umbenennen eines Verzeichnisses in einem Tar-Archiv mit PerlArchive::Tar . Das Archiv wird vollständig in den Speicher geladen. Dies ist eine intrinsische Einschränkung von 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 hat nicht die Fähigkeit, Mitglieder im laufenden Betrieb umzubenennen, aber pax(POSIXs Ersatz für cpiound tar). Es ist jedoch nicht möglich pax, aus einem Archiv sowohl Lese- als auch Schreibvorgänge durchzuführen. Sie können das Archiv als regulären Baum über AVFS verfügbar machen und ein neues Archiv mit erstellen pax. Dadurch werden die Dateinamen (mit Ausnahme der transformierten), Inhalte, Zeiten und Modi beibehalten, der Dateieigentum wird jedoch auf Sie zurückgesetzt (sofern sie nicht als Root ausgeführt werden).

mountavfs
cd "~/.avfs$PWD/old.tgz#"
pax -w -s '!bar!baz!' -s '!bar/!baz/' . | gzip >new.tgz
Gilles 'SO - hör auf böse zu sein'
quelle
GNU Tar bietet --transformseit mindestens 2010 die Möglichkeit, Dateien im laufenden Betrieb umzubenennen. Ein Beispiel finden Sie unter: scriptsandoneliners.blogspot.com/2019/11/…
A.Danischewski
Mit @ A.Danischewski --transformkönnen Sie Dateien umbenennen, wenn Sie ein Archiv erstellen oder extrahieren. Aber wie benennt man Dateien in einem Archiv um, ohne es zu extrahieren? (Extrahieren ist keine gute Lösung: Möglicherweise verfügen Sie nicht über genügend Speicherplatz. Möglicherweise verfügen Sie nicht über die Berechtigung, Besitzinformationen zu speichern. Möglicherweise können Sie Zeitstempel nicht exakt speichern.)
Gilles 'SO- hör auf, böse zu sein'
Okay, ja, ich habe gerade in Ihrem Post gesehen, dass "GNU tar nicht die Möglichkeit bietet, Mitglieder im laufenden Betrieb umzubenennen", sondern nur auf dem Weg hinein / hinaus. Wenn Sie die Namen in einem vorhandenen Archiv ändern möchten, können Sie es mit archivemount in ein Verzeichnis laden, die gewünschten Namen ändern und die Bereitstellung aufheben.
A.Danischewski
3

Sowohl sr_s hack als auch Gilles 'Antwort sehen sehr gut aus, aber wenn Ihr Problem nur der Name des Stammverzeichnisses des Ziel-Tarballs ist, während Sie rpmbuild ausführen, könnte eine andere Lösung darin bestehen, das %setupMakro neu zu definieren , um die erforderliche Dir-Umbenennung durchzuführen .

So etwas wie (Sie müssen dies an Ihre tatsächliche Konfiguration anpassen und verfeinern, insbesondere indem Sie das richtige Dekomprimierungswerkzeug ersetzen old-dirund desired-dirverwenden) in Ihrem ~/.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 .

Ich würde das ehrlich gesagt nicht tun, wenn es nicht die exotischste Situation wäre, aber deine könnte der Fall sein :)

Guido
quelle
2

Schauen Sie sich diese Seite einfach an, aber finden Sie die richtige Antwort an einer anderen Stelle:

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

Es besagt, dass Sie -n an das% setup-Makro übergeben können, um rpmbuild den Namen des Ordners der obersten Ebene im Tarball mitzuteilen

Niall
quelle
1

Hässlicher Hack, aber vielleicht hilft dir das, wenn du tarmit Symlinks blödelst:

$ mkdir a b
$ date >> b/foo
$ tar zcvf b-foo.tgz b/foo
$ rm -rf b
$ ln -s a b

$ tar zxvf b-foo.tgz                                                              
x b/foo: Cannot extract through symlink b
tar: Error exit delayed from previous errors.
$ tar zxvPf b-foo.tgz                                                             
x b/foo
$ ls a
foo

Wenn Sie darüber nachdenken, ist es wahrscheinlich nicht so, wie Sie rpmes nicht mit den Argumenten taranstellen wollen, oder? (Edit: Vielleicht können Sie dies mit einem kniffligen tarWrapper-Skript umgehen $PATH.)

sr_
quelle