使用预定义的卷数编写多卷 (GNU) `tar` 脚本

使用预定义的卷数编写多卷 (GNU) `tar` 脚本

我写了一个小脚本来测试(或提取)非常大型多卷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

相关内容