我写了一个小脚本来测试(或提取)非常大型多卷tar
存档(注意:使用 GNU 创建tar
),每个块都00x.tar
适合一张标准 DVD:
#!/bin/bash
d=$(dirname $0)
prf="someprefix"
last=$(ls -1 $d/*.tar | wc -l)
for i in $(eval echo {2..$last}); do echo "n $prf.00$i.tar"; done | tar -Mtvf ./$prf.001.tar --wildcards "$1"
笔记:
tar
无论有没有给定参数,管道都会工作$1
。- 当
d
卷和此脚本都位于另一个位置但它是从任意目录(例如您的$HOME
. - 本地
last
将解决 GNU 的问题tar
,从不检查工作目录中可用卷的数量。 - 在如此巨大的尺寸下,
$last
几乎不会大于 5(更不用说 9) - 因此00
.
好的,这有效。但完全摆脱循环将是甚至更好的。
像这样(--wildcards ...
这里省略):
eval echo -e "n\ $d/$prf.00{2..$last}.tar\\\n" | tar -Mtvf ./$prf.001.tar
然而,这仅适用于完全二卷。设置last
为例如 4,则会出现另一个问题,这是由于echo
在测试中省略管道而导致的:
n someprefix.002.tar
n someprefix.003.tar
n someprefix.004.tar
啊!那个空白是怎么进去的?tar
不喜欢那样。
一个“修复”(尽管非常黑客化)是通过在上面的管道中sed
插入 a 来“排除”空白。| sed 's/^ //'
相当丑陋,但无论如何,它确实有效。 :)
难道一开始就不能避免空白吗?
(tr
这里可能不是一个好的解决方案,因为我们需要一个替换字符(例如§
)来保留 ; 后的第一个空格n
;避免肮脏的黑客行为,没有办法告诉tr
“翻译除第一个空格之外的所有内容”。 )
答案1
$ eval echo -e "n\ $d/$prf.00{2..$last}.tar\\\n"
n someprefix.002.tar
n someprefix.003.tar
n someprefix.004.tar
那个空白是怎么进来的?
简而言之,答案是:这类似于在一堆名称以换行符结尾的文件上使用文件名扩展来回显一行时得到的输出。
如中所述大括号扩展:
要展开大括号的模式采用可选前导码的形式,后跟一系列逗号分隔的字符串或一对大括号之间的序列表达式,后跟可选后记。
所以 shell 正在评估
echo -e n\ dir/prefix00{2..4}.tar\\n
^preamble^^^^^^ ^postscript
并且,与文件名扩展一样,它在每个扩展元素之间插入一个空格,所以你得到(为了清楚起见,我在这里保留 \n 转义序列):
n dir/prefix002.tar\n n dir/prefix003.tar\n n dir/prefix004.tar\n\n
量子电子器件。
至于您的基本问题是如何在脚本中提供tar
信息以遍历多个卷,这里有两种方法:
- 用于
seq
生成n
命令:
seq -f "n $d/$prf.%03g.tar" 2 $last | tar -Mtvf $d/$prf.001.tar
- 编写一个简短的脚本来生成每个新卷名称并将其传递给
tar
的--new-volume-script
选项:
回显'#!/bin/sh'> ./newvol echo "printf $d/$prf.%03d.tar \$TAR_VOLUME >&\$TAR_FD" >> ./newvol chmod +x ./newvol tar -Mtvf $d/$prf.001.tar --new-volume-script=./newvol