Esto debería ayudar a identificar lo que está sucediendo en la respuesta de Johnny , así como a responder la pregunta de por qué esto funciona en Linux pero no en Mac.
El problema radica en el hecho de que Mac OS X usa bsdtar
, mientras que la mayoría de los sistemas Linux usan gnutar
.
Se puede instalar gnutar
en un Mac con Homebrew, utilizando brew install gnu-tar
, lo que enlazar simbólicamente gnutar
en /usr/local/bin
tan gtar
.
Si lo instala gnutar
, puede reproducir el problema siguiendo los pasos de la respuesta 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
Por lo tanto, obviamente gnutar
archiva las cosas de manera diferente, lo que hace bsdtar
que se ahogue con los duplicados. El hecho de que gtar -ztvf test.tar.gz
la segunda instancia de test/a
se archiva como a link to test/a
es relevante. Como señala Johnny en los comentarios, gnutar
almacenará duplicados como enlaces duros en lugar del archivo real, que se puede desactivar con --hard-dereference
.
Es decir, puede hacer lo siguiente:
$ 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
Sin embargo, en este caso, obviamente no controlas la creación del tarball, por --hard-dereference
lo que no es una opción. Afortunadamente, según la respuesta del OP , parece que este problema se ha solucionado en sentido ascendente.
No obstante, si alguien más se encuentra con este problema en el futuro y necesita una solución rápida o tiene un mantenedor ascendente que no responde, hay una solución alternativa.
Una vez que identifique cuál es el archivo duplicado, puede usar la --fast-read
opción de bsdtar
(tenga en cuenta que esta opción es solo parte de bsdtar
, no 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.
Entonces, en el ejemplo de juguete que he creado siguiendo el ejemplo de juguete en la respuesta de Johnny , el archivo duplicado es test/a
. Por lo tanto, puede evitar este problema haciendo lo siguiente:
# 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
Tenga en cuenta, además, que gnutar
está perfectamente feliz de descomprimir un archivo con duplicados que fue creado por sí mismo, incluso cuando la --hard-dereference
opción no se utilizó:
$ rm -r test
$ gtar -xvf test.tar.gz
test/
test/a
test/b
test/a
$ echo $?
0
$ ls test/
a b
Entonces esto responde a su pregunta de por qué se produce un error en Mac pero no en Linux. (La mayoría) de las distribuciones de Linux se envían con gnutar
, y dado que el tarball fue presumiblemente empaquetado gnutar
, no habrá ningún error al desempacar gnutar
, pero habrá un error al desempacar con bsdtar
.
Para una lectura y referencia adicional, uno puede mirar ¿Cuáles son las diferencias entre bsdtar y GNU tar? en Unix.SE.