通过将存档内容传输到 tar 命令来提取存档

通过将存档内容传输到 tar 命令来提取存档

我正在创建一个自解压存档,并且我已经完成了基本的工作。

tail -n+$ARCHIVE_START_LINE $0但是我想设置将存档内容提取到变量中的命令 。我无法让这部分工作

我在这里尝试了很多事情 - 下面显示了其中之一以供解释。 (请注意,这是一个简化的示例,问题是关于理解管道等以及解决问题。)

#!/bin/bash
export TMPDIR=`mktemp -d /tmp/selfextract.XXXXXX`
ARCHIVE_START_LINE=`awk '/^__ARCHIVE_BELOW__/ {print NR + 1; exit 0; }' $0`

# This works...
tail -n+$ARCHIVE_START_LINE $0 | tar xzv -C $TMPDIR

# .. but this is the kind of thing I want. But it doesn't work...
ARCHIVE_CONTENTS=`tail -n+$ARCHIVE_START_LINE $0`
echo $ARCHIVE_CONTENTS | tar xzv -C $TMPDIR
# I get: gzip: stdin is a multi-part gzip file -- not supported

我使用的是 Ubuntu 12.04

答案1

您的所有问题都已在中得到解释为什么我的 shell 脚本会因为空格或其他特殊字符而卡住?,但我会在这里重复相关部分。

首先,$var在 shell 脚本中并不意味着“变量的值var”,它的意思是“获取变量的值var,将其拆分为单词并将每个单词解释为通配符模式”。为了避免这些额外的步骤,请在变量替换周围加上双引号:"$var"表示“变量的值var”。始终在变量替换和命令替换两边加上双引号除非您知道并理解为什么需要将它们排除在外。

其次,echo并不完全打印它的参数:它解释一些选项,并且在某些 shell 中,它解释反斜杠转义序列。此外,还echo打印尾随换行符,您可以使用该-n选项将其删除。 Gzipped 数据看起来从来都不像一个选项,bashecho默认情况下会按字面意思处理反斜杠,但一般来说,不要echo在未知数据上使用,printf %s而是使用。

printf %s "$ARCHIVE_CONTENTS" | tar xzv -C "$TMPDIR"

这可以保证准确地输入变量的ARCHIVE_CONTENTStar

剩下的问题是,如果不使用根本不同的方法就无法解决,大多数 shell(我见过的除了 zsh 之外的所有 shell)都会在第一个空字节处截断变量的值(这是因为它们使用C 空终止字符串在引擎盖下)。因此,该变量ARCHIVE_CONTENTS实际上只包含存档文件的开头,直到第一个空字节。您不能使用 shell 来操作二进制数据。

答案2

为什么不像以前那样使用此处文档?

 #!/bin/bash
 export TMPDIR=`mktemp -d /tmp/selfextract.XXXXXX`

 ## other stuff

 base64 -d <<EOF | tar xvf -C $TMPDIR
 ## base64 encoded
 EOF

你以这种方式生成base64编码

 tar cf - my_dir | base64 > /some/place

(包括它的自解压存档留给读者)

答案3

您可能无意中对存档内容进行了 shell 扩展。尝试引用您的变量。

代替

echo $ARCHIVE_CONTENTS | tar xzv -C $TMPDIR

echo "$ARCHIVE_CONTENTS" | tar xzv -C $TMPDIR

您可能还需要避免附加换行符echo -n

相关内容