Dies sollte helfen, herauszufinden, was in Johnnys Antwort vor sich geht , und die Frage zu beantworten , warum dies unter Linux, aber nicht auf Mac funktioniert.
Das Problem liegt in der Tatsache, dass Mac OS X verwendet bsdtar
, während die meisten Linux-Systeme verwenden gnutar
.
Sie können installieren gnutar
auf einem Mac mit Homebrew verwenden brew install gnu-tar
, die Symlink wird gnutar
in /usr/local/bin
so gtar
.
Wenn Sie installieren gnutar
, können Sie das Problem anhand der Schritte in Johnnys Antwort reproduzieren .
$ brew install gnu-tar
==> Downloading https://homebrew.bintray.com/bottles/gnu-tar-1.28.yosemite.bottle.2.tar.gz
######################################################################## 100.0%
==> Pouring gnu-tar-1.28.yosemite.bottle.2.tar.gz
==> Caveats
gnu-tar has been installed as "gtar".
If you really need to use it as "tar", you can add a "gnubin" directory
to your PATH from your bashrc like:
PATH="/usr/local/opt/gnu-tar/libexec/gnubin:$PATH"
==> Summary
🍺 /usr/local/Cellar/gnu-tar/1.28: 13 files, 1.6M
$ mkdir test
$ touch test/a test/b
$ gtar -zcvf test.tar.gz test test/a # make the archive with gnutar
test/
test/a
test/b
test/a
$ gtar -ztvf test.tar.gz
drwxr-xr-x adamliter/staff 0 2015-07-28 22:41 test/
-rw-r--r-- adamliter/staff 0 2015-07-28 22:41 test/a
-rw-r--r-- adamliter/staff 0 2015-07-28 22:41 test/b
hrw-r--r-- adamliter/staff 0 2015-07-28 22:41 test/a link to test/a
$ rm -r test
$ tar -xvf test.tar.gz # try to unpack the archive with bsdtar
x test/
x test/a
x test/b
x test/a: Can't create 'test/a'
tar: Error exit delayed from previous errors.
$ echo $?
1
Offensichtlich werden die gnutar
Dinge also anders archiviert, sodass bsdtar
Duplikate erstickt werden. Die Tatsache, gtar -ztvf test.tar.gz
dass die zweite Instanz von test/a
als a archiviert wird, link to test/a
ist relevant. Wie Johnny in den Kommentaren hervorhebt, gnutar
werden Duplikate als feste Links und nicht als tatsächliche Dateien gespeichert, mit denen deaktiviert werden kann --hard-dereference
.
Das heißt, Sie könnten Folgendes tun:
$ mkdir test
$ touch test/a test/b
$ gtar -zcvf test.tar.gz test test/a --hard-dereference
test/
test/a
test/b
test/a
$ gtar -ztvf test.tar.gz test
drwxr-xr-x adamliter/staff 0 2015-07-28 23:49 test/
-rw-r--r-- adamliter/staff 0 2015-07-28 23:49 test/a
-rw-r--r-- adamliter/staff 0 2015-07-28 23:49 test/b
-rw-r--r-- adamliter/staff 0 2015-07-28 23:49 test/a # note that this is no longer a link
$ rm -r test
$ tar -xvf test.tar.gz # unpack with bsdtar
x test/
x test/a
x test/b
x test/a
$ echo $?
0
$ ls test/
a b
In diesem Fall haben Sie jedoch offensichtlich keinen Einfluss auf die Erstellung des Tarballs. Daher ist dies --hard-dereference
keine Option. Zum Glück scheint es , basierend auf der Antwort des OP , dass dieses Problem durch den Upstream behoben wurde.
Wenn jedoch in Zukunft jemand anderes auf dieses Problem stößt und eine schnelle Lösung benötigt oder einen nicht reagierenden Upstream-Betreuer hat, gibt es eine Problemumgehung.
Sobald Sie die doppelte Datei identifiziert haben, können Sie die --fast-read
Option von verwenden bsdtar
(beachten Sie, dass diese Option nur ein Teil von ist bsdtar
, nicht gnutar
):
-q (--fast-read)
(x and t mode only) Extract or list only the first archive entry that matches each pattern or filename operand. Exit as soon as each specified pat-
tern or filename has been matched. By default, the archive is always read to the very end, since there can be multiple entries with the same name
and, by convention, later entries overwrite earlier entries. This option is provided as a performance optimization.
In dem Spielzeugbeispiel, das ich in Anlehnung an das Spielzeugbeispiel in Johnnys Antwort erstellt habe , lautet die doppelte Datei test/a
. So können Sie dieses Problem vermeiden, indem Sie folgendermaßen vorgehen:
# this set of commands picks up from the first set of commands
# i.e., the following assumes a tarball that was *not* made with
# the --hard-dereference option, although this will work just as well
# with one that was
$ tar -xvqf test.tar.gz test/a # unarchive the first instance of test/a
x test/a
$ tar -xvf test.tar.gz --exclude test/a # unarchive everything except test/a
x test/
x test/b
$ echo $?
0
$ ls test/
a b
Beachten Sie außerdem, dass Sie gnutar
gerne ein Archiv mit Duplikaten entpacken, die selbst erstellt wurden, auch wenn die --hard-dereference
Option nicht verwendet wurde:
$ rm -r test
$ gtar -xvf test.tar.gz
test/
test/a
test/b
test/a
$ echo $?
0
$ ls test/
a b
Dies beantwortet also Ihre Frage, warum ein Fehler auf Mac, aber nicht auf Linux ausgegeben wird. (Die meisten) Linux-Distributionen werden mit ausgeliefert gnutar
, und da der Tarball vermutlich mit gepackt wurde , tritt gnutar
beim Entpacken kein Fehler auf gnutar
, aber beim Entpacken mit bsdtar
.
Zur weiteren Lektüre und zum Nachschlagen möchte man vielleicht einen Blick auf Was sind die Unterschiede zwischen bsdtar und GNU tar? auf Unix.SE.