Cela devrait aider à identifier ce qui se passe dans la réponse de Johnny , ainsi qu'à répondre à la question de savoir pourquoi cela fonctionne sur Linux mais pas sur Mac.
Le problème réside dans le fait que Mac OS X utilise bsdtar
, alors que la plupart des systèmes Linux utilisent gnutar
.
Vous pouvez installer gnutar
sur un Mac avec Homebrew, en utilisant brew install gnu-tar
, qui sera un lien symbolique gnutar
vers /usr/local/bin
as gtar
.
Si vous installez gnutar
, vous pouvez reproduire le problème en suivant les étapes de la réponse de Johnny .
$ 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
Il est donc évident que les gnutar
choses sont archivées différemment d'une manière qui provoque l' bsdtar
étouffement des doublons. Le fait qui gtar -ztvf test.tar.gz
indique que la deuxième instance de test/a
est archivée en tant que link to test/a
est pertinent. Comme Johnny le souligne dans les commentaires, gnutar
stockera les doublons sous forme de liens physiques plutôt que le fichier réel, qui peut être désactivé avec --hard-dereference
.
Autrement dit, vous pouvez effectuer les opérations suivantes:
$ 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
Cependant, dans ce cas, vous ne contrôlez évidemment pas la création de l'archive tar, ce --hard-dereference
n'est donc pas une option. Heureusement, sur la base de la réponse du PO , il semble que ce problème ait été résolu par l'amont.
Néanmoins, si quelqu'un d'autre rencontre ce problème à l'avenir et a besoin d'une solution rapide ou a un responsable en amont qui ne répond pas, il existe une solution de contournement.
Une fois que vous avez identifié le fichier en double, vous pouvez utiliser l' --fast-read
option de bsdtar
(notez que cette option n'est qu'une partie de bsdtar
, pas 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.
Ainsi, dans l'exemple de jouet que j'ai créé à la suite de l'exemple de jouet dans la réponse de Johnny , le fichier en double est test/a
. Ainsi, vous pouvez éviter ce problème en procédant comme suit:
# 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
Notez, en outre, que gnutar
vous êtes parfaitement heureux de décompresser une archive avec des doublons qui a été créée par elle-même, même lorsque l' --hard-dereference
option n'a pas été utilisée:
$ rm -r test
$ gtar -xvf test.tar.gz
test/
test/a
test/b
test/a
$ echo $?
0
$ ls test/
a b
Cela répond donc à votre question de savoir pourquoi une erreur est lancée sur Mac mais pas Linux. (La plupart) des distributions Linux sont livrées avec gnutar
, et comme l'archive tar était vraisemblablement empaquetée avec gnutar
, il n'y aura pas d'erreur lors du déballage avec gnutar
, mais il y aura une erreur lors du déballage avec bsdtar
.
Pour plus de lecture et de référence, on pourrait vouloir regarder quelles sont les différences entre bsdtar et GNU tar? sur Unix.SE.