将文件存储在BASH脚本中

12

有没有办法在BASH脚本中存储二进制数据,以便稍后在该脚本中将其导入到程序中?

目前(在Mac OS X上)我正在执行以下操作:

play sound.m4a
# do stuff

我想要做类似于这样的事情:

SOUND <<< the m4a data, encoded somehow?
END
echo $SOUND | play
#do stuff

有没有一种方法可以实现这个?

7个回答

11

将其进行Base64编码。例如:

$ openssl base64 < sound.m4a

然后在脚本中:

S=<<SOUND
YOURBASE64GOESHERE
SOUND

echo $S | openssl base64 -d | play

4
不完全正确。S=<<SOUND 可能不会按你所想的那样运作(而且无论如何,变量S将不包含此处文档的内容)。 - gniourf_gniourf

6

我知道这个帖子比较老,但是我想改进Sionide21的回答,因为他的解决方案将二进制数据存储在一个不必要的变量中。

openssl base64 -d <<SOUND | play
YOURBASE64DATAHERE
SOUND

注意:HereDoc语法要求您不要缩进最后的'SOUND',并且当我缩进'YOURBASE64DATAHERE'部分时,base64解码有时会失败。因此,最好的做法是将Base64数据以及结束令牌保持未缩进状态。
我发现这个方法可以更优雅地在Shell脚本中存储二进制数据,但我已经按照这里描述的方式解决了这个问题。唯一的区别是我以这种方式传输了一些tar-bzipped文件。我的平台知道一个单独的base64二进制文件,所以我不必使用openssl。
base64 -d <<EOF | tar xj
BASE64ENCODEDTBZ
EOF

4

有一种 Unix 格式叫做 shar(shell archive),它允许你将二进制数据存储在一个 shell 脚本中。使用 shar 命令创建 shar 文件。


1
这个答案需要通过一个例子来改进。 - Elijah Lynn

2
当我这样做时,我使用一个shell文档,通过atob进行了管道传输。
function emit_binary {
  cat << 'EOF' | atob
  --junk emitted by btoa here
  EOF
}

这里文档中的'EOF'单引号可以防止参数在此处被扩展。

atobbtoa是非常古老的程序,因此它们经常缺失于现代Unix发行版中。虽然效率稍低但更为普遍的替代方案是使用mimencode -b来代替btoamimencode将编码为base64 ASCII格式,相应的解码命令是mimencode -b -u而不是atob。 另外,openssl命令也可以进行base64编码。


@Sionide:请点击链接获取源代码,或者您可以使用 mimencode - Norman Ramsey

1
如果只使用一个数据块,我使用的技巧是在文件末尾放置一个“数据开始”标记,然后在脚本中使用sed过滤掉前导内容。例如,创建以下内容作为“play-sound.bash”:
#!/bin/bash

sed '1,/^START OF DATA/d' $0 | play
exit 0
START OF DATA

然后,您只需将数据附加到此文件的末尾:
cat sound.m4a >> play-sound.bash

执行该脚本后,应直接播放声音。

1

这是我很久以前写的一些代码,它将一个可执行文件打包到一个bash脚本中。我记不清它的工作原理了,但我猜你可以很容易地修改它来实现你想要的功能。

#!/usr/bin/perl

use strict;

print "Stub Creator 1.0\n";

unless($#ARGV == 1)
{
    print "Invalid argument count, usage: ./makestub.pl InputExecutable OutputCompressedExecutable\n";
    exit;
}

unless(-r $ARGV[0])
{
    die "Unable to read input file $ARGV[0]: $!\n";
}

my $OUTFILE;
open(OUTFILE, ">$ARGV[1]") or die "Unable to create $ARGV[1]: $!\n";

print "\nCreating stub script...";

print OUTFILE "#!/bin/bash\n";
print OUTFILE "a=/tmp/\`date +%s%N\`;tail -n+3 \$0 | zcat > \$a;chmod 700 \$a;\$a \${*};rm -f \$a;exit;\n";

close(OUTFILE);

print "done.\nCompressing input executable and appending...";
`gzip $ARGV[0] -n --best -c >> $ARGV[1]`;
`chmod +x $ARGV[1]`;

my $OrigSize;
$OrigSize = -s $ARGV[0];

my $NewSize;
$NewSize = -s $ARGV[1];

my $Temp;

if($OrigSize == 0)
{
    $NewSize = 1;
}

$Temp = ($NewSize / $OrigSize) * 100;
$Temp *= 1000;
$Temp = int($Temp);
$Temp /= 1000;

print "done.\nStub successfully composed!\n\n";
print <<THEEND;
Original size: $OrigSize
New size:      $NewSize
Compression:   $Temp\%

THEEND

0

由于Python在OS X上默认可用,您可以按照以下步骤操作:

ENCODED=$(python -m base64 foo.m4a)

然后按照以下方式解码:

echo $ENCODED | python -m base64 -d  | play

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接