Заметка дня #10 Получая архив откуда-либо, его содержимое всегда… — Остальные 90% — TG.ME

Заметка дня #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
👍15🔥3❤1
April 9, 2025 873 15