Вопрос или проблема
Я создал такую простую структуру директорий:
$ 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
при распаковке архивов с абсолютными путями, чтобы контролировать структуру созданных каталогов.