У меня довольно странная проблема, и я не могу понять, что происходит. У меня есть файл tgz, scip-3.2.0.tgz , который выдает ошибку, когда я пытаюсь его распаковать. Ошибка возникает только в OS X (у меня 10.10.4). Я могу извлечь файл без ошибок на компьютере с Linux под управлением CentOS 6.6. Ошибка возникает как при использовании команды командной строки, так tar
и при использовании утилиты архивации. Я отправил электронное письмо в список рассылки SCIP, и у меня есть тот же хэш SHA-1, что и у другого пользователя ( e085a4a3591eddf945dcb365d97d2512c267e374
), так что ошибки загрузки не было. Они не уверены, что происходит.
Вот ошибка, которую я получаю, когда пытаюсь распаковать с помощью утилиты архивации:
На случай, если изображение когда-либо сломается, текст на изображении говорит следующее:
Не удалось расширить «scip-3.2.0.tgz» на «Рабочий стол».
(Ошибка 1 - Операция не разрешена.)
И когда я пытаюсь распаковать через командную строку, я получаю вот такой результат . tar: Error exit delayed from previous errors.
Меня беспокоит последняя строка ( ). Я не вижу, чем это вызвано. Похоже , что архив извлекается без проблем, но я не доверяю ему с этой ошибкой.
Кто-нибудь знает, что вызывает это?
[править]
Присмотревшись немного ближе к выводу, строка 1108 содержит ошибку:
x scip-3.2.0/applications/Coloring/Makefile: Can't create 'scip-3.2.0/applications/Coloring/Makefile'
Это должно помочь определить, что происходит в ответе Джонни , а также ответить на вопрос, почему это работает на Linux, но не на Mac.
Проблема заключается в том, что Mac OS X использует bsdtar
файлы gnutar
.
Вы можете установить gnutar
на Mac с Homebrew, используя brew install gnu-tar
, который будет символически ссылаться gnutar
на ./usr/local/bin
gtar
Если вы установите gnutar
, вы можете воспроизвести проблему, используя шаги , описанные в ответе Джонни .
$ 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
Таким образом, очевидно gnutar
, архивирует вещи по-разному, что заставляет bsdtar
задыхаться от дубликатов. Тот факт, что gtar -ztvf test.tar.gz
указывает на то, что второй экземпляр test/a
заархивирован как a link to test/a
, имеет значение. Как отмечает Джонни в комментариях, gnutar
дубликаты будут храниться как жесткие ссылки, а не как фактический файл, который можно отключить с помощью --hard-dereference
.
То есть вы могли бы сделать следующее:
$ 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
Однако в этом случае вы, очевидно, не контролируете создание архива, так что --hard-dereference
это не вариант. К счастью, судя по ответу ОП , кажется, что эта проблема была исправлена восходящим потоком.
Тем не менее, если кто-то еще столкнется с этой проблемой в будущем и будет нуждаться в быстром исправлении или у него не будет ответа вышестоящего сопровождающего, есть обходной путь.
Как только вы определите, что представляет собой дубликат файла, вы можете использовать --fast-read
параметр bsdtar
(обратите внимание, что этот параметр является только частью bsdtar
, а не 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.
Итак, в примере с игрушкой, который я создал после примера с игрушкой в ответе Джонни , файл-дубликат — это test/a
. Таким образом, вы можете избежать этой проблемы, выполнив следующие действия:
# 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
Учтите, кроме того, что gnutar
совершенно спокойно распаковывает архив с дубликатами, который был создан сам, даже когда --hard-dereference
опция не использовалась:
$ rm -r test
$ gtar -xvf test.tar.gz
test/
test/a
test/b
test/a
$ echo $?
0
$ ls test/
a b
Итак, это ответ на ваш вопрос о том, почему ошибка возникает на Mac, а не на Linux. (Большинство) дистрибутивов Linux поставляются с gnutar
, и, поскольку tar-архив предположительно был упакован с gnutar
, при распаковке с gnutar
, не будет ошибки, но будет ошибка при распаковке с bsdtar
.
Для дальнейшего чтения и справки можно посмотреть , каковы различия между bsdtar и GNU tar? на Unix.SE.
gtar -tcvf
, gnutar достаточно «умен», чтобы оптимизировать второй файл копии как ссылку, а не дублировать его в архиве.--hard-dereference
опции отключает это поведение.Существование файла-дубликата в архиве не должно делать его недействительным или невозможным для извлечения в OSX, поскольку по умолчанию tar перезаписывает дубликаты.
Итак, меня немного смущает поведение в вашем Gist - OSX tar позволяет дублировать файлы в архиве (возврат к его первоначальному назначению в качестве утилиты для архивирования лент , поэтому он позволяет добавлять файлы в конец ленточного архива, и при восстановлении архива самая новая версия файла перезапишет старую(ие) версию(и))
Только при наличии параметра "-k" tar должен предупреждать о уже существующих файлах.
Здесь я создал архив с дубликатом файла, а затем без проблем извлек его. Только когда я добавил параметр -k, он предупредил меня о дублирующемся файле:
Macbook> tar --version
bsdtar 2.8.3 - libarchive 2.8.3
Macbook> mkdir test
Macbook> touch test/a test/b
Macbook> tar -zcvf test.tar.gz test test/a
a test
a test/a
a test/b
a test/a
Macbook> tar -ztvf test.tar.gz
drwxr-xr-x 0 user group 0 Jul 28 10:42 test/
-rw-r--r-- 0 user group 0 Jul 28 10:42 test/a
-rw-r--r-- 0 user group 0 Jul 28 10:42 test/b
-rw-r--r-- 0 user group 0 Jul 28 10:42 test/a
Macbook> rm -r test
Macbook> tar -xvf test.tar.gz
x test/
x test/a
x test/b
x test/a
Macbook> echo $?
0
Macbook> rm -r test
Macbook> tar -k -xvf test.tar.gz
x test/
x test/a
x test/b
x test/a: Already exists
tar: Error exit delayed from previous errors.
Macbook> echo $?
1
Простая проблема с umask, похоже, тоже не виновата, я попытался изменить свой umask на 0777, и я все еще могу извлечь архив:
Macbook> tar -xvf test.tar
x test/
x test/a
x test/b
x test/a
Macbook> ls -l test
ls: test: Permission denied
Macbook> sudo ls -l test
total 0
---------- 1 someuser wheel 0 Jul 28 13:48 a
---------- 1 someuser wheel 0 Jul 28 13:48 b
Я думал, что смогу воспроизвести проблему, преднамеренно добавив в архив недоступную для записи директорию, но это не сработало, tar не обновил разрешения для директории при извлечении архива:
Macbook> mkdir -p testdir1/test testdir2/test
Macbook> touch testdir1/test/{a,b} testdir2/test/a
Macbook> chmod -w testdir2/test
Macbook> touch testdir2/test/b
touch: testdir2/test/b: Permission denied
Macbook> find testdir* -ls | awk '{print $3, $11}'
drwxrwx--- testdir1
drwxrwx--- testdir1/test
-rw-rw---- testdir1/test/a
-rw-rw---- testdir1/test/b
drwxrwx--- testdir2
dr-xr-x--- testdir2/test
-rw-rw---- testdir2/test/a
Macbook> cd testdir1
Macbook> tar -cvf ../test.tar test/*
a test/a
a test/b
Macbook> cd ../testdir2
Macbook> tar -rvf ../test.tar test
a test
a test/a
Macbook> cd ..
Macbook> tar -tvf ./test.tar
-rw-rw---- 0 username groupname 0 Jul 28 15:40 test/a
-rw-rw---- 0 username groupname 0 Jul 28 15:40 test/b
-rw-rw---- 0 username groupname 0 Jul 28 15:40 test/a
dr-xr-x--- 0 username groupname 0 Jul 28 15:40 test/
-rw-rw---- 0 username groupname 0 Jul 28 15:40 test/a
Macbook> tar -xvf test.tar
x test/a
x test/b
x test/a
x test/
x test/a
Macbook>
Я также попытался изменить разрешения для test/a на 000, добавить его в архив, а затем добавить еще один test/a, но он тоже работал нормально:
drwxrwx--- 0 username groupname 0 Jul 28 15:40 test/
-rw-rw---- 0 username groupname 0 Jul 28 15:40 test/a
-rw-rw---- 0 username groupname 0 Jul 28 15:40 test/b
dr-xr-x--- 0 username groupname 0 Jul 28 15:40 test/
---------- 0 username groupname 0 Jul 28 15:40 test/a
-rw-rw---- 0 username groupname 0 Jul 28 15:40 test/a
Так что я бы очень хотел увидеть исходный архив, вызвавший проблему, и посмотреть, что могло быть в этом архиве, чтобы вызвать эту проблему.
Если имя файла и каталог имеют одно и то же имя, у tar возникают проблемы с распаковкой, но выдается довольно четкое сообщение об ошибке:
Macbook> tar -xvf test.tar
x test/
x test/dir1/
x test/dir1/a
x test/
x test/dir1: Can't remove already-existing dir
tar: Error exit delayed from previous errors.
(если конфликт произошел наоборот, т.е. сначала появился файл, а потом каталог с таким же именем, tar просто удаляет его и создает каталог:
Macbook> tar -xvf test.tar
x test/
x test/dir1
x test/
x test/dir1/
x test/dir1/a
Оказывается, утилита OS X tar была правильной! В архиве действительно была ошибка. В этой ветке электронной почты это обсуждается более подробно, но проблема в том, что в архиве есть дубликат файла . Ребята из SCIP исправляют архив, пока я это печатаю.
[edit]
Недавно обновленный файл scip-3.2.0.tgz теперь извлекается просто отлично! Хэш SHA-1 нового tgz равен 5b4e8283f4a5bf9e50f9a62d4320d6f5f50c8476
.
[править 2]
Дело не в том, что в архиве ошибка. Просто bsdtar
, который поставляется с OS X, обрабатывает повторяющиеся файлы иначе, чем gnutar
, который поставляется с Linux. Ответ @Adam Liter здесь дает подробное объяснение того, что происходит.
-k
параметр, который заставлял бы его предупреждать о уже существующих файлах. К сожалению, они уже обновили scip-3.2.0.tgz
файл, чтобы удалить дубликат, поэтому я не могу проверить этот архив.tar
реагирует по-разному при попытке извлечь scip-3.2.0/applications/Coloring/Makefile
дважды в зависимости от вашего файла umask
. Если 1-й созданный не оставляет вам права на запись, 2-я попытка не удалась.tar
встроенный в OS X 10.10.4 выдает ошибку в этом конкретном архиве. Возможно, Джонни подразумевает, что в реализации OS X действительно есть ошибка, tar
потому что, согласно спецификации tar, дубликат файла не должен вызывать ошибку.tar
формат не запрещает элементы с одинаковыми именами, не означает, что каждый архив с одинаковыми именами будет успешно извлечен. Как упоминает @daniel, если первый файл имеет ограничительные разрешения, его tar
последующая перезапись может оказаться невозможной. Другой возможностью может быть архив, включающий как файл, так и каталог с одним и тем же именем — второй может быть не в состоянии заменить первый.Есть альтернативное бесплатное легкое программное обеспечение для архивирования, которое я использую для Mac OSX. Он называется Keka , и я использую его для наиболее конкретной распаковки 7zip. Более того, он может распаковывать другие типы, такие как .rar, .tar, .gz и т. Д. Он также работал для конкретного tar-файла OP, но я попытался это сделать после того, как @Geoff упомянул, что команда работает над восстановлением файла.
ПопробуйПопробуйЕще раз
Джефф
tar
команде, которая поставляется с OS X.ПопробуйПопробуйЕще раз
gunzip -c scip-3.2.0.tgz | tar xopf -
работе из командной строки, как если бы вы использовали ее для своего сценария?Джефф
gunzip
работает нормально, но когда я пытаюсь извлечь несжатый архив, возникает ошибка.Джефф
Дэн
umask
на 2 системах, на которых вы запускали этоtar
?Джефф
umask
это 0022. На машине с Linux это 0002.