在 BASH 脚本中存储文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2308268/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Storing files inside BASH scripts
提问by JP.
Is there a way to store binary data inside a BASH script so that it can be piped to a program later in that script?
有没有办法将二进制数据存储在 BASH 脚本中,以便稍后在该脚本中将其通过管道传输到程序?
At the moment (on Mac OS X) I'm doing
目前(在 Mac OS X 上)我正在做
play sound.m4a
# do stuff
I'd like to be able to do something like:
我希望能够执行以下操作:
SOUND <<< the m4a data, encoded somehow?
END
echo $SOUND | play
#do stuff
Is there a way to do this?
有没有办法做到这一点?
采纳答案by Sionide21
Base64 encode it. For example:
Base64 编码它。例如:
$ openssl base64 < sound.m4a
and then in the script:
然后在脚本中:
S=<<SOUND
YOURBASE64GOESHERE
SOUND
echo $S | openssl base64 -d | play
回答by Andreas
I know this is like riding a dead horse since this post is rather old, but I'd like to improve Sionide21 answer as his solution stores the binary data in a variable which is not necessary.
我知道这就像骑一匹死马,因为这篇文章已经很老了,但我想改进 Sionide21 的答案,因为他的解决方案将二进制数据存储在一个不必要的变量中。
openssl base64 -d <<SOUND | play
YOURBASE64DATAHERE
SOUND
Note: HereDoc Syntax requires that you don't indent the last 'SOUND' and base64 decoding sometimes failed on me when i indented that 'YOURBASE64DATAHERE' section. So it's best practice to keep the Base64 Data as well the end-token unindented.
注意:HereDoc 语法要求您不要缩进最后一个“声音”,当我缩进“YOURBASE64DATAHERE”部分时,base64 解码有时会失败。因此,最佳做法是保持 Base64 数据以及未缩进的最终令牌。
I've found this looking for a more elegant way to store binary data in shell scripts, but i had already solved it like described here. Only difference is I'm transporting some tar-bzipped files this way. My platform knows a separate base64 binary so I don't have to use openssl.
我发现这正在寻找一种更优雅的方式在 shell 脚本中存储二进制数据,但我已经像这里描述的那样解决了它。唯一的区别是我以这种方式传输一些 tar 压缩文件。我的平台知道一个单独的 base64 二进制文件,所以我不必使用 openssl。
base64 -d <<EOF | tar xj
BASE64ENCODEDTBZ
EOF
回答by Joshua Smith
回答by Norman Ramsey
When I've done this I've used a shell here document piped through atob.
完成此操作后,我在此处使用了通过管道传输的 shell 文档atob。
function emit_binary {
cat << 'EOF' | atob
--junk emitted by btoa here
EOF
}
the single quotes around 'EOF'prevent parameter expansion in the body of the here document.
周围的单引号'EOF'可防止此处文档正文中的参数扩展。
atoband btoaare veryold programs, and for some reason they are often absent from modern Unix distributions. A somewhat less efficient but more ubiquitous alternative is to use mimencode -binstead of btoa. mimencodewill encode into base64 ASCII. The corresponding decoding command is mimencode -b -uinstead of atob. The opensslcommand will also do base64 encoding.
atob并且btoa是非常古老的程序,出于某种原因,现代 Unix 发行版中通常没有它们。一种效率稍低但更普遍的替代方法是使用mimencode -b代替btoa。 mimencode将编码为 base64 ASCII。对应的解码命令是mimencode -b -u代替atob。该openssl命令还将进行 base64 编码。
回答by Sam
Here's some code I wrote a long time ago that packs a choice executable into a bash script. I can't remember exactly how it works, but I suspect you could pretty easily modify it to do what you want.
这是我很久以前写的一些代码,它将选择可执行文件打包到 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
回答by kenorb
Since Python is available on OS X by default, you can do as below:
由于默认情况下 Python 在 OS X 上可用,您可以执行以下操作:
ENCODED=$(python -m base64 foo.m4a)
Then decode it as below:
然后解码如下:
echo $ENCODED | python -m base64 -d | play
回答by Uditha Desilva
If it's a single block of data to use, the trick I've used is to put a "start of data" marker at the end of the file, then use sed in the script to filter out the leading stuff. For example, create the following as "play-sound.bash":
如果它是要使用的单个数据块,我使用的技巧是在文件末尾放置一个“数据开始”标记,然后在脚本中使用 sed 过滤掉前导内容。例如,将以下内容创建为“ play-sound.bash":
#!/bin/bash
sed '1,/^START OF DATA/d' cat sound.m4a >> play-sound.bash
| play
exit 0
START OF DATA
Then, you can just append your data to the end of this file:
然后,您可以将数据附加到此文件的末尾:
##代码##and now, executing the script should play the sound directly.
现在,执行脚本应该直接播放声音。

