转换 tar 存档的路径而不提取它

Jos*_* R. 11 tar

GNUtar(1)有一个简洁的选项,称为--transform. 从手册页:

--transform, --xform EXPRESSION
使用 sed 替换 EXPRESSION 来转换文件名

这允许在提取存档时动态转换路径名,以便您可以控制提取的位置和方式。

我的问题是,有没有办法在原位执行类似的转换;即,不提取存档?

例子

[user@host]$ tar tf test.tar
./foo/blah  ./foo/bleh
[user@host]$ some_deep_magic 's/foo/bar/' test.tar
[user@host]$ tar tf test.tar
./bar/blah  ./bar/bleh
Run Code Online (Sandbox Code Playgroud)

用例

我正在tar向基本上一无所知的最终用户分发一个存档,并希望它能够在不受我干扰的情况下提取到正确的路径中。我试图避免提取存档,重命名目录和重新打包的琐碎解决方案,因为存档很大。

Jos*_*tin 3

您可以使用 archivemount 或 mountavfs 挂载存档并再次重新创建它

archivemount tarfile.tar /mnt
cd /mnt
tar cf /tmp/tarfile.tar --transform 's/foo/bar/' .
Run Code Online (Sandbox Code Playgroud)

归档文件系统上的写入操作将在卸载时执行完全重写,因此对于大文件来说似乎不是一个好的选择。

编辑

我不知道实现细节,但似乎我们正在将写入文件保存到文件系统步骤。

只是测试一下解决问题,(通过我的 /usr 的 tar)

#!/bin/bash

# try to avoid slab cache issues 
cat /tmp/usr.tar > /dev/null

T="$(date +%s)"
tar xf /tmp/usr.tar
tar cf usr.tar usr --transform 's/usr/foo/'
T="$(($(date +%s)-T))"
echo "Tar/Untar seconds: ${T}"

T="$(date +%s)"
archivemount -o readonly -o nobackup /tmp/usr.tar /mnt
tar cf usr.tar /mnt  --transform 's/usr/foo/'
umount /mnt
T="$(($(date +%s)-T))"
echo "Archivemount seconds: ${T}"

T="$(date +%s)"
mountavfs
cd '/root/.avfs/tmp/usr.tar#'
tar cf /tmp/test/usr.tar   --transform 's/usr/foo/' .
T="$(($(date +%s)-T))"
echo "Avfs seconds: ${T}"
Run Code Online (Sandbox Code Playgroud)

输出:

Tar/Untar seconds: 480
Archivemount seconds:  failure, a lot of read errors.
Avfs seconds: 217
Run Code Online (Sandbox Code Playgroud)

所以 Avfs 获胜!