Почему команда tar создает эту структуру директорий при извлечении tar-файла?

Вопрос или проблема

Я создал такую простую структуру директорий:

$ tree testdir/
testdir/
├── subdir1
│   ├── file1.txt
│   └── file2.txt
├── subdir2
│   ├── file3.txt
│   └── file4.txt

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

tar cvf /home/myuser/testdir/testdir_tarfile.tar --exclude=/home/myuser/testdir/testdir_tarfile.tar /home/myuser/testdir

Теперь я хочу снова извлечь файлы (вместе с их структурой директорий). Сначала создадим целевую директорию:

$ mkdir /home/myuser/testdir/target_dir

А теперь извлечем файл tar в целевую директорию:

tar xf /home/myuser/testdir/testdir_tarfile.tar -C /home/myuser/testdir/target_dir/

Структура файлов, получившаяся в результате, выглядит так:

$ tree testdir/
testdir/
├── subdir1
│   ├── file1.txt
│   └── file2.txt
├── subdir2
│   ├── file3.txt
│   └── file4.txt
├── target_dir
│   └── home
│       └── myuser
│           └── testdir
│               ├── subdir1
│               │   ├── file1.txt
│               │   └── file2.txt
│               └── subdir2
│                   ├── file3.txt
│                   └── file4.txt
└── testdir_tarfile.tar

Почему целевая директория теперь содержит подпапки “home” и “myuser”? Я хотел бы, чтобы она содержала только “subdir1” и “subdir2”, т.е. как оригинальная архивированная директория.

Почему целевая директория теперь содержит подпапки “home” и “myuser”? Я хотел бы, чтобы она содержала только “subdir1” и “subdir2”, т.е. как оригинальная архивированная директория.

Вам также нужно использовать опцию -C при сжатии. Например:

tar -cvf "$HOME/testdir_tarfile.tar" -C "$HOME" testdir

что по сути эквивалентно:

( cd && tar -cvf "testdir_tarfile.tar" testdir )

Как видно из подробного вывода, стоит отметить, что это создает TAR с относительными путями:

testdir/
testdir/subdir2/
testdir/subdir2/file2.txt
testdir/subdir2/file1.txt
testdir/subdir1/
testdir/subdir1/file2.txt
testdir/subdir1/file1.txt

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

tar -cvf "$HOME/testdir_tarfile.tar" "$HOME/testdir"
mkdir -p "$HOME/testdir/target_dir"
tar --strip-components=2 -xf "$HOME/testdir_tarfile.tar" -C "$HOME/testdir/target_dir/"
tree "$HOME/testdir/target_dir/"
/home/user/testdir/target_dir/
└── testdir
    ├── subdir1
    │   ├── file1.txt
    │   └── file2.txt
    └── subdir2
        ├── file1.txt
        └── file2.txt

4 директории, 4 файла

Ответ или решение

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

Почему появилась структура "home/myuser/testdir"?

Когда вы запустили команду для создания архива:

tar cvf /home/myuser/testdir/testdir_tarfile.tar --exclude=/home/myuser/testdir/testdir_tarfile.tar /home/myuser/testdir

Вы архивировали полный путь к каталогу testdir (от корня) вместо того, чтобы использовать относительные пути. В результате в архив были добавлены абсолютные пути, начиная от корневого каталога (/home/myuser/testdir/...), что при распаковке привело к созданию структуры каталогов home/myuser/testdir внутри вашего целевого каталога (target_dir).

Как это исправить?

Чтобы избежать данной проблемы и создать архив с относительными путями, вам нужно использовать опцию -C, позволяющую сменить текущий каталог перед архивированием. Таким образом, команда для создания архива будет выглядеть следующим образом:

tar -cvf "$HOME/testdir_tarfile.tar" -C "$HOME" testdir

Эта команда заархивирует только содержимое testdir, сохранив относительные пути внутри архива.

Извлечение без лишних каталогов

Когда вы захотите извлечь данные из созданного архива, использовав вышеуказанную команду для его создания, у вас не возникнет проблем с избыточными каталогами. Если вы уже создали архив с абсолютными путями, и вам нужно их извлечь, вы можете воспользоваться параметром --strip-components.

Пример команды для извлечения без лишних директорий:

mkdir -p "$HOME/testdir/target_dir"
tar --strip-components=3 -xf "$HOME/testdir_tarfile.tar" -C "$HOME/testdir/target_dir/"

Здесь --strip-components=3 удаляет три уровня каталога, позволяя вам оставить внутри target_dir только subdir1 и subdir2, как в оригинальной структуре.

Заключение

Использование правильного подхода при создании архива с помощью команды tar позволяет избежать ненужных уровней каталогов. Следуйте рекомендациям по использованию опции -C для создания архивов с относительными путями и используйте параметр --strip-components при распаковке архивов с абсолютными путями, чтобы контролировать структуру созданных каталогов.

Оцените материал
Добавить комментарий

Капча загружается...