855просмотров
9 апреля 2025 г.
statsScore: 941
Заметка дня #10 Получая архив откуда-либо, его содержимое всегда полезно проверить перед распаковкой - в противном случае следующие за ней 15 минут можно потратить, собирая рассыпавшиеся по всей директории файлы. Иногда поместить файлы в общую директорию в архиве просто нельзя (например, формат APK накладывает свои ограничения), а иногда создатель архива решает не заморачиваться. Если нам не повезло и файлы не собраны в общей директории, то самый простой и надёжный способ обезопаситься от "сбежавших" файлов - создать временную пустую директорию, переместить в неё архив и распаковать его там. В случае с GNU tar ключ -C позволяет указать имя директории, в которую надо извлечь файлы, но первый шаг всё равно придётся выполнить: tar не создаст эту директорию, если её не существует:
# Create some archive
$ mkdir -p a/b/c
$ echo 123 > a/b/c/d
$ tar -cf some_archive.tar a # Look at files inside
$ tar -tf some_archive.tar a/
a/b/
a/b/c/
a/b/c/d # Try to unpack to a non-existent directory
$ tar -xf some_archive.tar -C tmp_dir
tar: tmp_dir: Cannot open: No such file or directory
tar: Error is not recoverable: exiting now Фокус, однако, можно провернуть, воспользовавшись менее популярным ключом --transform, принимающим выражение sed для преобразования имён файлов:
$ tar -tf some_archive.tar \ --transform 's,^,tmp_dir/,' --show-transformed-names
tmp_dir/a/
tmp_dir/a/b/
tmp_dir/a/b/c/
tmp_dir/a/b/c/d $ tar -xf some_archive.tar --transform 's,^,tmp_dir/,' $ cat tmp_dir/a/b/c/d
123 В примере выше мы заменили в названиях файлов все начала строк (^) на имя директории tmp_dir/, и tar при распаковке архива создал её, принимая за часть оригинального названия файла. Действие ключа --transform не ограничено добавлением префиксов - имена файлов можно крутить, как только позволит фантазия:
# Substitute b for tmp_dir
$ tar -tf some_archive.tar \ --show-transformed-names --transform 's,b,tmp_dir,'
a/
a/tmp_dir/
a/tmp_dir/c/
a/tmp_dir/c/d # Remove b subdirectory (// is the same as /)
$ tar -tf some_archive.tar \ --show-transformed-names --transform 's,b,,'
a/
a//
a//c/
a//c/d Здесь важно заметить, что tar по умолчанию не создаёт файлы по абсолютным путям и всегда отбрасывает ведущий первый символ / из их имён. Замена s,^,/tmp/, распакует архив не в директорию /tmp/ в корне ФС, а в tmp/, созданную в текущей директории, и выведет предупреждение:
tar -tf some_archive.tar \ --transform 's,^,/tmp/,' --show-transformed-names
tar: Removing leading `/' from member names
tmp/a/
tmp/a/b/
tmp/a/b/c/
tmp/a/b/c/d Если мы уверены, что всё делаем верно и нам действительно нужны абсолютные пути, то ключом -P можно разрешить создавать такие файлы:
$ tar -tf some_archive.tar \ --transform 's,^,/tmp/,' --show-transformed-names -P
/tmp/a/
/tmp/a/b/
/tmp/a/b/c/
/tmp/a/b/c/d #tip