Tarfile.TarFile.add: примеры (PYTHON)
tarfile.TarFile.add(name, arcname, recursive, filter): NoneОписание функции tarfile.TarFile.add
Метод add() принадлежит классу TarFile модуля tarfile. Его применяют для добавления файла или каталога в открытый tar-архив. Это основной способ наполнения архивов содержимым.
Метод используют, когда требуется программно создать или обновить tar-архив, упаковав в него выбранные данные. Поддерживаются все распространенные форматы архивов: gzip, bzip2, xz.
Аргументы метода
- name (строка, обязательный): путь к файлу или каталогу в файловой системе, который необходимо добавить.
- arcname (строка, необязательный): альтернативное имя, под которым объект будет сохранен в архиве. Если не указано, используется name.
- recursive (булевый, необязательный, по умолчанию True): если True и добавляется каталог, то все его содержимое включается в архив рекурсивно. При значении False каталог добавляется пустым.
- filter (функция, необязательный): функция, применяемая к каждому добавляемому объекту TarInfo для его модификации или фильтрации. Если функция возвращает None, объект исключается из архива.
Возвращаемое значение
Метод не возвращает значений (None). Его результат - изменение состояния объекта архива, к которому его применили.
Примеры использования функции add
Базовый пример добавления одного файла.
import tarfile
with tarfile.open('archive.tar', 'w') as tar:
tar.add('document.txt')
print('Файл добавлен')
Файл добавлен
Добавление файла с переименованием внутри архива.
import tarfile
with tarfile.open('archive.tar', 'w') as tar:
tar.add('data.csv', arcname='backup/data.csv')
print('Файл добавлен как backup/data.csv')
Файл добавлен как backup/data.csv
Добавление каталога без рекурсивного обхода.
import tarfile
with tarfile.open('archive.tar', 'w') as tar:
tar.add('my_folder', recursive=False)
print('Пустая папка добавлена')
Пустая папка добавлена
Использование фильтра для исключения файлов по расширению.
import tarfile
def filter_exclude_py(tarinfo):
if tarinfo.name.endswith('.py'):
return None
return tarinfo
with tarfile.open('archive.tar', 'w') as tar:
tar.add('project_folder', filter=filter_exclude_py)
print('Добавлены все файлы, кроме .py')
Добавлены все файлы, кроме .py
Похожие функции в Python
- tarfile.TarFile.addfile(tarinfo, fileobj=None): добавляет в архив информацию о файле (TarInfo) и, опционально, данные из файлового объекта. Этот метод подходит, когда требуется предварительно настроить метаданные (права доступа, время модификации) или добавить данные из потока, а не из файла на диске.
- shutil.make_archive(base_name, format, root_dir, ...): высокоуровневая функция для создания архивов различных форматов (zip, tar, gztar и др.). Ее применение удобно для быстрого создания стандартных архивов без тонкой настройки, в то время как TarFile.add дает полный контроль над процессом.
Альтернативы в других языках программирования
PHP: Класс PharData. Отличается интеграцией с форматом Phar, но умеет работать и с обычными tar-архивами.
$phar = new PharData('archive.tar');
$phar->addFile('/path/to/file.txt', 'internal/path.txt');
echo 'Файл добавлен.\n';
Файл добавлен.
JavaScript (Node.js): Библиотека tar. Работа асинхронная, основана на потоках.
const tar = require('tar');
tar.c(
{gzip: true, file: 'archive.tar.gz'},
['file1.txt', 'folder']
).then(() => console.log('Архив создан'));
Архив создан
Java: Библиотека Apache Commons Compress. Требует более многословного кода для создания архива по сравнению с Python.
import org.apache.commons.compress.archivers.tar.*;
import java.io.*;
TarArchiveEntry entry = new TarArchiveEntry("file.txt");
entry.setSize(new File("file.txt").length());
tarOutput.putArchiveEntry(entry);
// ... копирование данных файла
tarOutput.closeArchiveEntry();
Golang: Пакет archive/tar. Работа ведется через создание заголовков (Header) и последовательную запись данных.
file, _ := os.Open("data.txt")
info, _ := file.Stat()
hdr, _ := tar.FileInfoHeader(info, "")
tw.WriteHeader(hdr)
io.Copy(tw, file)
Типичные ошибки при использовании
Попытка добавить несуществующий файл или каталог.
import tarfile
try:
with tarfile.open('archive.tar', 'w') as tar:
tar.add('non_existent_file.txt')
except FileNotFoundError as e:
print(f'Ошибка: {e}')
Ошибка: [Errno 2] No such file or directory: 'non_existent_file.txt'
Использование архива, открытого в режиме только для чтения, для добавления файлов.
import tarfile
# Сначала создаем архив
with tarfile.open('archive.tar', 'w') as tar:
tar.add('file1.txt')
# Пытаемся добавить в архив, открытый для чтения
try:
with tarfile.open('archive.tar', 'r') as tar:
tar.add('file2.txt')
except tarfile.ReadError as e:
print(f'Ошибка: {e}')
Ошибка: cannot write to a read-only archive
Ошибки, связанные с правами доступа при чтении исходного файла.
import tarfile
import os
# Создаем файл без прав на чтение
with open('secret.txt', 'w') as f:
f.write('data')
os.chmod('secret.txt', 0o000) # Убираем все права
try:
with tarfile.open('archive.tar', 'w') as tar:
tar.add('secret.txt')
except PermissionError as e:
print(f'Ошибка доступа: {e}')
finally:
os.chmod('secret.txt', 0o644) # Возвращаем права
os.remove('secret.txt')
Ошибка доступа: [Errno 13] Permission denied: 'secret.txt'
Изменения в последних версиях Python
В Python 3.8 был добавлен ключевой параметр filter. До его введения для фильтрации или модификации добавляемых файлов приходилось использовать более сложные обходные пути, например, предварительный сбор списка файлов и их индивидуальное добавление через TarFile.gettarinfo и TarFile.addfile с модификацией объектов TarInfo.
Начиная с версии Python 3.12, параметр filter стал рекомендуемым способом фильтрации, в то время как устаревший параметр exclude (который присутствовал в похожей функции tarfile.create) был окончательно удален.
Расширенные примеры использования
Добавление только файлов с определенными расширениями, игнорируя все остальные.
import tarfile
import os
def filter_only_images(tarinfo):
if tarinfo.isreg() and tarinfo.name.endswith(('.png', '.jpg', '.jpeg')):
return tarinfo
return None
with tarfile.open('images.tar', 'w') as tar:
tar.add('photos_folder', filter=filter_only_images)
members = tar.getmembers()
print(f'Добавлено файлов: {len(members)}')
for m in members:
print(f' - {m.name}')
Добавлено файлов: 3 - photos_folder/cat.jpg - photos_folder/dog.png - photos_folder/scenery.jpeg
Изменение владельца и прав доступа для файлов при добавлении в архив.
import tarfile
def set_root_owner(tarinfo):
tarinfo.uid = 0
tarinfo.gid = 0
tarinfo.uname = 'root'
tarinfo.gname = 'root'
tarinfo.mode = 0o644 # Стандартные права на чтение/запись
return tarinfo
with tarfile.open('system_backup.tar', 'w') as tar:
tar.add('configs/app.conf', filter=set_root_owner)
info = tar.getmember('configs/app.conf')
print(f'Владелец в архиве: {info.uname}:{info.gname}')
print(f'Права в архиве: {oct(info.mode)}')
Владелец в архиве: root:root Права в архиве: 0o644
Рекурсивное добавление каталога с исключением скрытых файлов и папок (начинающихся с точки).
import tarfile
import os
def exclude_hidden(tarinfo):
base_name = os.path.basename(tarinfo.name)
if base_name.startswith('.'):
return None
return tarinfo
with tarfile.open('project.tar.gz', 'w:gz') as tar:
tar.add('my_project', filter=exclude_hidden)
names = tar.getnames()
print('Добавленные объекты:')
for name in sorted(names):
if '/.' not in name: # Проверка, что внутри путей тоже нет скрытых
print(f' {name}')
Добавленные объекты: my_project my_project/LICENSE my_project/README.md my_project/src my_project/src/main.py
Создание архива с сохранением символических ссылок как ссылок, а не как файлов, на которые они указывают.
import tarfile
import os
# Создаем тестовую структуру
os.makedirs('test_dir', exist_ok=True)
with open('test_dir/real_file.txt', 'w') as f:
f.write('content')
os.symlink('real_file.txt', 'test_dir/link.txt')
with tarfile.open('with_links.tar', 'w') as tar:
# По умолчанию filter=None, ссылки добавляются как ссылки
tar.add('test_dir')
for member in tar.getmembers():
print(f'{member.name} - islink: {member.islnk() or member.issym()}')
# Уборка
import shutil
shutil.rmtree('test_dir')
test_dir - islink: False test_dir/real_file.txt - islink: False test_dir/link.txt - islink: True