tar: добавить все файлы и каталоги в текущий каталог, ВКЛЮЧАЯ .svn и т. д.


90

Я пытаюсь создать каталог tar.gz и использовать

tar -czf workspace.tar.gz *

Полученный tar включает .svnкаталоги в подкаталогах, но НЕ в текущем каталоге (поскольку он *расширяется только до `` видимых '' файлов, прежде чем он будет передан в tar

Я попытался

tar -czf workspace.tar.gz .вместо этого, но тогда я получаю сообщение об ошибке, потому что "." изменилось при чтении:

tar: ./workspace.tar.gz: file changed as we read it

Есть ли уловка, позволяющая *сопоставить все файлы (в том числе с префиксом точки) в каталоге?

(с использованием bash в Linux SLES-11 (2.6.27.19)


5
Может этот вопрос относится к суперпользователю?
Peter Jaric

Ответы:


76

Не создавайте tar-файл в каталоге, который вы собираете:

tar -czf /tmp/workspace.tar.gz .

делает свое дело, за исключением того, что при распаковке файлы распаковываются по всему текущему каталогу. Лучше сделать:

cd ..
tar -czf workspace.tar.gz workspace

или, если вы не знаете имя каталога, в котором находились:

base=$(basename $PWD)
cd ..
tar -czf $base.tar.gz $base

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


Один комментарий в обсуждении гласит:

Мне [...] нужно исключить верхний каталог, а мне [...] нужно поместить tar в базовый каталог.

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

Со второй частью комментария можно справиться одним из двух способов:

  1. Либо: создайте файл в другом месте - /tmpэто одно из возможных мест - а затем переместите его обратно в исходное место после его завершения.
  2. Или: если вы используете GNU Tar, воспользуйтесь --exclude=workspace.tar.gzопцией. Строка после символа =- это образец - это самый простой образец - точное совпадение. Возможно, вам потребуется указать, работаете --exclude=./workspace.tar.gzли вы в текущем каталоге вопреки рекомендациям; вам может потребоваться указать, работаете --exclude=workspace/workspace.tar.gzли вы на один уровень выше, как предлагается. Если вам нужно исключить несколько файлов tar, используйте ' *', как в --exclude=./*.gz.

1
Хороший ответ, но у меня есть ситуация, когда я вынужден запустить эту команду внутри каталога, который нужно упаковать. У меня недостаточно прав для запуска его снаружи.
Hexodus

Безусловно, идеальное место для упаковки - / tmp.
Андре Феллоуз

46

Если вы действительно не хотите включать верхний каталог в архив (а это вообще плохая идея):

tar czf workspace.tar.gz -C /path/to/workspace .

Мне нужно исключить верхний каталог, и мне нужно поместить tar в базовый каталог.
Micha

@Micha создайте bash-скрипт для архивации и копирования файла после
Fedir RYKHTIK

2
Думаю, вам не хватает - в -czf.
UpTheCreek

10
man tar: первым аргументом tar должна быть функция; либо одна из букв Acdrtux, либо одно из длинных имен функций. Функциональная буква не требует префикса- , и ее можно комбинировать с другими однобуквенными параметрами.
Рхайров

4
Все еще не работает, у меня все еще есть "." как верхний каталог в моем архиве
A. Gille

43

Нужно сделать несколько шагов:

  1. Замените *на, .чтобы также включить скрытые файлы.
  2. Чтобы создать архив в том же каталоге, --exclude=workspace.tar.gzможно использовать a , чтобы исключить сам архив.
  3. Чтобы предотвратить tar: .: file changed as we read itошибку, когда архив еще не создан, убедитесь, что он существует (например, с помощью touch), чтобы параметр --exclude соответствовал имени файла архива. (Не совпадает, файл не существует)

В совокупности это приводит к следующему сценарию:

touch workspace.tar.gz
tar -czf workspace.tar.gz --exclude=workspace.tar.gz .

7
Я прочитал все ответы и комментарии, и это лучший способ создать архив в том же каталоге. Из этого ответа я также понял, почему возникает эта ошибка.
Szymon Sadło

Если вы хотите , чтобы увидеть прогресс , в то время как это сжатие файла деготь, вы можете добавить дополнительный флаг --verbose, например , так: -czvf.
Mastrianni

18

в каталоге, который хотите сжать (текущий каталог), попробуйте следующее:

tar -czf workspace.tar.gz . --exclude=./*.gz

2
Но теперь он жалуется, что файл "." изменено во время чтения. Могу ли я быть уверен, что все файлы включены?
Jaan

1
Это исключает все .gzфайлы в каталоге.
omerfarukdogan 05

12

Вы можете включить скрытые каталоги, вернувшись в каталог и выполнив:

cd ..
tar czf workspace.tar.gz workspace

Предполагая, что каталог, который вы хотите сжать, назывался рабочей областью.


И это также позволяет избежать проблемы с изменением файла.
Джонатан Леффлер,

Не работает, если у пользователя нет разрешения на запись в родительскую папку.
Иоахим Вагнер

Именно @JoachimWagner!
p01ymath

1
@JoachimWagner. Если у вас нет разрешения на запись, измените его на:tar -czf /path/to/where/you/do/have/permission/workspace.tar.gz workspace
bramp

1
Пришлось вынуть -перед тем, czfкак заставить работать. В противном случае я получал Cannot stat: No such file or directoryсообщение об ошибке.
Phemelo Khetho

6

Вы можете исправить .форму, используя --exclude:

tar -czf workspace.tar.gz --exclude=workspace.tar.gz .

5

Обновление: я добавил исправление для комментария OP.

tar -czf workspace.tar.gz .

действительно изменит текущий каталог, но почему бы не поместить файл в другое место?

tar -czf somewhereelse/workspace.tar.gz .
mv somewhereelse/workspace.tar.gz . # Update

После этого файл будет обработан, и он должен находиться в рабочей области - это немного некрасиво, но это просто необходимо (все это просто обходной путь ...)
Micha

Хорошо, я добавлю исправление для этого :)
Питер Ярик,

И если вам нужно иметь возможность запускать это повторно, добавьте 'rm workspace.tar.gz' перед строкой tar.
Peter Jaric

Если вы хотите поместить весь диск в тот же диск, похоже, у вас не так много вариантов.
BeeOnRope

4

Собственно проблема в параметрах сжатия. Хитрость заключается в том, чтобы передать результат дегтя в компрессор вместо использования встроенных опций. Кстати, это также может дать вам лучшее сжатие, поскольку вы можете установить дополнительные параметры сжатия.

Минимальная смола:

tar --exclude=*.tar* -cf workspace.tar .

Подключите к компрессору по вашему выбору. Этот пример подробный и использует xz с максимальным сжатием:

tar --exclude=*.tar* -cv . | xz -9v >workspace.tar.xz

Решение было протестировано на Ubuntu 14.04 и Cygwin на Windows 7. Это ответ сообщества вики, поэтому не стесняйтесь редактировать, если обнаружите ошибку.


Спасибо! Спасенная мама жизнь
Стивен

2

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

ls -1A | xargs -d "\n" tar cfz my.tar.gz

Если у вас уже есть my.tar.gzв текущем каталоге, вы можете найти это:

ls -1A | grep -v my.tar.gz | xargs -d "\n" tar cfz my.tar.gz

Имейте в виду, что у xargs есть определенный предел (см. xargs --show-limits). Таким образом, это решение не будет работать, если вы пытаетесь создать пакет, который имеет много записей (каталогов и файлов) в каталоге, который вы пытаетесь использовать tar.


1

Хороший вопрос. В ZSH вы можете использовать модификатор подстановки (D), что означает «точечные файлы». Сравните:

ls $HOME/*

а также

ls $HOME/*(D)

Это правильно исключает специальные записи каталога .и ... В Bash вы можете использовать .*для явного включения точечных файлов:

ls $HOME/* $HOME/.*

Но это включает в себя .и .., так что это не то, что вы искали. Я уверен, что есть способ сделать *точечные файлы соответствия и в bash.


В bash используйте .??*для соответствия всем файлам точек, .а не и ... Это не дает файлов с односимвольными точками (например, .a). Чтобы получить и их, используйте более сложный .[^.]*.
Скотт Минстер

1

Еще одно решение, предполагающее, что количество элементов в папке невелико:

tar -czf workspace.tar.gz `ls -A`

( ls -Aпечатает обычные и скрытые файлы, но не «.» и «..», как это ls -aпроисходит.)


0
tar -czf workspace.tar.gz .??* *

При указании .??*будут включены файлы с точками и каталоги, в которых после точки будет не менее 2 символов. Обратной стороной является то, что он не будет включать файлы / каталоги с одним символом после точки, например .a, если они есть.


0

Если место на диске не проблема, это тоже может быть очень легко сделать:

mkdir backup
cp -r ./* backup
tar -zcvf backup.tar.gz ./backup

0

У меня была похожая ситуация. Я думаю, что лучше всего создать tar в другом месте, а затем использовать -C, чтобы указать tar базовый каталог для сжатых файлов. Пример:

tar -cjf workspace.tar.gz -C <path_to_workspace> $(ls -A <path_to_workspace>)

Таким образом, нет необходимости исключать собственный tar-файл. Как отмечено в других комментариях, -A выведет список скрытых файлов.


0

10 лет спустя у вас есть альтернатива tar, проиллюстрированная Git 2.30 (Q1 2021), которая использует " git archive" ( man ) для создания tar-архива выпуска вместо tar.
(Вам не нужен Git 2.30 для применения этой альтернативы)

См. Commit 4813277 (11 октября 2020 г.) и commit 93e7031 (10 октября 2020 г.) Рене Шарфе ( rscharfe) .
(Объединено Junio ​​C Hamano - gitster- в коммите 63e5273 , 27 октября 2020 г.)

Makefile: используйте git init / add / commit / archive для dist-doc

Подписано: Рене Шарфе

Уменьшите зависимость от внешних инструментов, создав архивы распространения для документации HTML и справочных страниц с помощью ( mangit команд ) вместо tar. Это дает записи архива те же метаданные, что и в архиве dist для двоичных файлов.

Так что вместо:

tar cf ../archive.tar .

Вы можете использовать только Git:

git -C workspace init
git -C workspace add .
git -C workspace commit -m workspace
git -C workspace archive --format=tar --prefix=./ HEAD^{tree} > workspace.tar
rm -Rf workspace/.git

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


-1

Пожалуй, findсамый простой способ использовать:

find . -maxdepth 1 -exec tar zcvf workspace.tar.gz {} \+

find . -maxdepth 1найдет все файлы / каталоги / символические ссылки / и т.д. в текущем каталоге и выполнит команду, указанную в -exec. Значок {}в команде означает, что список файлов идет сюда и \+означает, что команда будет запускаться как:

tar zcvf workspace.tar.gz .file1 .file2 .dir3

вместо того

tar zcvf workspace.tar.gz .file1
tar zcvf workspace.tar.gz .file2
tar zcvf workspace.tar.gz .dir3

-J в руководстве - это --xz; в сочетании с -c - это только начало того, что компьютер назовет «забавой» :)
Ricalsin

Ха-ха, мой домашний мини-сервер больше ограничен дисковым пространством, чем процессором :) Хороший момент; Я заменю его на использование gzip.
Эндрю Ганнерсон
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.