Тар ведущий слэш

tar czf dist.tgz --exclude=".gitignore" .

Это создает файлы в tar с начальным "./", что позже превращается в проблему, когда серверу нужно извлечь части tar.

Может кто-нибудь сказать мне, как упаковать его, чтобы не было ведущих "./"?

6 ответов

Попробуйте --xform опция, которая использует выражение замены типа sed. Это позволяет вам изменять ссылки на пути, идущие в архив, а не обрабатывать их во время извлечения (например, с помощью --strip-components).

tar --exclude=.gitignore -cz --xform s:'./':: -f dist.tgz ./

Чтобы вывести список файлов по мере их обработки, добавьте -v а также --show-transformed-name опции:

tar --exclude=.gitignore -cvz --xform s:'./':: --show-transformed-name -f dist.tgz ./

Аргумент для передачи --xform имеет следующую структуру: s/regexp/replace/[flags] Обратите внимание, что в моем примере я использовал : как разделитель; Вы можете использовать любой символ, который хотите, если вы используете его последовательно. Хорошая ссылка здесь.

Есть несколько способов сделать это, на многие из которых уже намекали в этом вопросе, а некоторые - нет. Это моя попытка собрать их все (со ссылками) и показать примеры для удобного чтения, позволяя читателю выбрать тот, который соответствует его потребностям.


Пример дерева ввода

Это структура, которая будет описана в следующих примерах.

.dotfile
dir/
  .hidden
  file.txt
root.txt

Решение POSIX (кроссплатформенное, кросс-оболочка)

Вы можете использовать pax вместо tar, как указал Фил П.

Обычное поведение:

$ pax -wzvf ../ball.tar.gz .
[…]
$ pax -zf ../ball.tar.gz
.
./.dotfile
./dir
./dir/.hidden
./dir/file.txt
./root.txt

Без косой черты:

$ pax -wzvf ../ball.tar.gz -s ':^\./::' .
[…]
$ pax -zf ../ball.tar.gz
.
.dotfile
dir
dir/.hidden
dir/file.txt
root.txt

Shell Globbing (кросс-платформенное) решение

Вы также можете использовать * вместо . как указывал ott--. Это решение в основном является краткой формой ответа chutz, поскольку оболочка расширит звездочку в приведенном ниже примере на все не скрытые файлы, прежде чем передавать их в качестве аргументов tar программа.

Без косой черты (но обратите внимание на отсутствие корневого уровня .dotfile):

$ tar -czvf ../ball.tar.gz *
[…]
$ tar -tzf ../ball.tar.gz
dir/
dir/.hidden
dir/file.txt
root.txt

Если вам не нужно упаковывать точечные файлы в CWD, все готово.

Если вам все равно, вы не без защиты. На многих снарядах (например, bash) можно включить точечные файлы в глобус оболочки, изменив параметр оболочки. С bash это делается с shopt:

dotglob

Если установлено, bash включает имена файлов, начинающиеся с "." в результатах расширения пути.

$ shopt -s dotglob  # Include dot-files in pathname expansions
$ tar -czvf ../ball.tar.gz *
[…]
$ shopt -u dotglob  # Restore shell's default globbing behavior
$ tar -tzf ../ball.tar.gz
.dotfile
dir/
dir/.hidden
dir/file.txt
root.txt

Решение GNU (Linux)

Используйте --xform, как упомянуто в ответе Джордана Бонитатиса.

Обычное поведение:

$ tar -czvf ../ball.tar.gz .
[…]
$ tar -tzf ../ball.tar.gz
./
./root.txt
./.dotfile
./dir/
./dir/file.txt
./dir/.hidden

Без косой черты:

$ tar -czvf ../ball.tar.gz --xform 's:^\./::' . [--show-transformed-names|--show-stored-names]
[…]
$ tar -tzf ../ball.tar.gz
./
root.txt
.dotfile
dir/
dir/file.txt
dir/.hidden

Решение BSD (Mac OS X)

Используйте -s, который обманчиво похож на pax / sed, но не совсем, как показано ниже.

Обычное поведение:

$ tar -czvf ../ball.tar.gz .
[…]
$ tar -tzf ../ball.tar.gz
./
./.dotfile
./dir/
./root.txt
./dir/.hidden
./dir/file.txt

Без косой черты:

$ tar -czvf ../ball.tar.gz -s '/.//' .
tar: Removing leading '/' from member names
[…]
$ tar -tzf ../ball.tar.gz 
.dotfile
dir/
root.txt
dir/.hidden
dir/file.txt

Не уверен какая версия tar это так, но обычно вы должны указать, какие файлы вы хотите архивировать. подобно tar c . сжать все в локальном каталоге. Запустив вашу команду на моей машине, я получаю:

tar: Cowardly refusing to create an empty archive

Итак, если вы не хотите, чтобы получить ведущую ./, что вы получаете, когда вы сжимаете локальный каталог .Вы можете просто указать файлы напрямую. Например:

> tar c hosts fstab | tar tv
-rw-r--r-- root/root      1225 2012-10-20 13:37 hosts
-rw-r--r-- root/root       678 2012-05-13 22:09 fstab

Я использую это:

tar --create --directory a_dir $(ls --almost-all a_dir) > archive.tar

Это будет список всех файлов и каталогов (за исключением . а также ..) каталога a_dir и добавить их в архив. --directory options устанавливает корень, из которого tar начнет искать файлы.

В старых версиях tar он использовал полные пути, которые вы указали в tar, но это как-то проблематично, так как в старые времена форматирования может потребоваться вторая копия чего-либо и непреднамеренное расширение архива tar, может перезаписать существующий файл или файлы.

Таким образом, в самых последних версиях tar-бинарного файла, распространяемого практически в любом дистрибутиве Linux, знак./ ставится в начале каждого файла, который он упаковывает, так что непреднамеренное расширение расширяет архив в текущий рабочий каталог и ниже.

Я не уверен, почему это вызывает такую ​​проблему для вас. если вы находитесь на нужном уровне каталогов, где вы хотите расширить этот архив, он сделает именно это. Например, допустим, у вас есть файл как

/tmp/myarchive.tar

и давайте предположим, что содержимое архива

./etc/hosts./etc/profile./etc/passwd./etc/group

если вы раскроете этот архив, пока ваш текущий рабочий каталог - / (то есть корневой уровень), эти файлы будут перезаписаны на существующие

/ и т.д. / хосты
/ И т.д. / профиль
/ И т.д. / пароль
/ И т.д. / группа

если это то, что вы хотите, у вас есть это. Но скажем, вы хотели, чтобы файлы хоста были только из этого архива, но внезапно вы стерли файлы профиля passwd и group. Надеюсь, у вас есть хорошая резервная копия на данный момент, чтобы вы могли получить их обратно

Но, если вы относитесь к типу системного администратора, который избегает находиться на корневом уровне, если он / она не нуждается в этом намеренно, скорее всего, вы вошли в систему и расположены в каталоге / home / some-user, или если вы вошли в систему как пользователь root, вы находятся в / корневой каталог. Допустим, ваш in / root. когда вы выполняете команду

# tar -xvf /tmp/myarchive.tar

вы закончите с

/ корень / и т.д. / хосты
/ Корень / и т.д. / профиль
/ Корень / и т.д. / пароль
/ Корень / и т.д. / группа

нет вреда, нет фола. затем

# mv /root/etc/hosts /etc/hosts

Вуаля. Вы достигли своей цели.

Я использовал tar -P сохранить ведущие / (скорее, чем ./) Не совсем понятно, поможет ли это в вашем случае.

-P, --absolute-names
    don't strip leading '/'s from file names 

человек смола

Другие вопросы по тегам