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