如何使用 Bash 编写二进制文件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5582778/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 20:23:03  来源:igfitidea点击:

How to write a binary file using Bash?

bashawkbusybox

提问by elcuco

My problem is that I need to create a file with this exact bytes: 48, 00, 49, 00.

我的问题是我需要用这个确切的字节创建一个文件:48, 00, 49, 00.

I cannot use C, perl, other scripting language (the target is an embedded device). I tried this using awk, and in desktop it does work:

我不能使用 C、perl、其他脚本语言(目标是嵌入式设备)。我用 awk 试过这个,在桌面上它确实有效:

# awk  'BEGIN{ printf "%c%c%c%c", 48, 00, 49, 00 }' | hexdump
0000000 0030 0031                              
0000004

However the target platform is running busybox v1.13.2 and this code does not work there. The awk version there does not output ascii "0" (all other values are ok).

但是目标平台正在运行 busybox v1.13.2 并且此代码在那里不起作用。那里的 awk 版本不输出 ascii "0"(所有其他值都可以)。

What are your recommendations?

你有什么建议?

回答by yohann.martineau

you can use the following command:

您可以使用以下命令:

echo -n -e \x48\x00\x49\x00 > myfile

回答by Michael Back

POSIX AWK standard says that passing a 0 to AWK's printf with %c format can result in unspecified behaviour. However... POSIX echo also is very limited, and though octal and hexadecimal specifiers (and -n) will work on GNU echo and BASH built-in... They may not work everywhere. To maximize the chance that you get consistent behaviour on all POSIX systems, it is better to use the shell command line's printf than either of these.

POSIX AWK 标准表示,将 0 传递给 %c 格式的 AWK 的 printf 会导致未指定的行为。然而...... POSIX echo 也非常有限,虽然八进制和十六进制说明符(和 -n)可以在 GNU echo 和 BASH 内置......它们可能无法在任何地方工作。为了最大限度地提高在所有 POSIX 系统上获得一致行为的机会,最好使用 shell 命令行的 printf 而不是其中任何一个。

$ printf '0
$ printf '0
echo -n -e \0060\0000\0061\0000  | hexdump
01
# busybox printf '\x74\x65\x73\x74' > /sdcard/test.txt
0' | od -An -tx1 48 00 49 00
01
# busybox hexdump -C /sdcard/test.txt
00000000  74 65 73 74                                       |test|
00000004
0' | od -An -tx1 30 00 31 00

This looks odd to me though... You may be wanting to output 0x48, 0x00, 0x49, 0x00 -- which looks like a pretty pilot number in octal:

虽然这对我来说看起来很奇怪......你可能想要输出 0x48, 0x00, 0x49, 0x00 -- 这看起来像一个漂亮的八进制飞行员数字:

# cat /sdcard/test.txt
test

回答by flolo

you could try echo, that also allows arbitrary ascii chars (those numbers are octal numbers).

你可以试试 echo,它也允许任意的 ascii 字符(这些数字是八进制数字)。

le16 () { # little endian 16 bit binary output 1st param: integer to 2nd param: file 
  v=`awk -v n= 'BEGIN{printf "%04X", n;}'`
  echo -n -e "\x${v:2:2}\x${v:0:2}" >> 
}

le32 () { # 32 bit version
  v=`awk -v n= 'BEGIN{printf "%08X", n;}'`
  echo -n -e "\x${v:6:2}\x${v:4:2}\x${v:2:2}\x${v:0:2}" >> 
}

回答by BuvinJ

I needed to write binary files from hex using busybox within an old Android shell. This printfwith a redirect worked in my use case.

我需要在旧的 Android shell 中使用 busybox 从十六进制编写二进制文件。这printf在我的用例中使用了重定向。

Write the binary data in hex:

以十六进制写入二进制数据:

channels=2
bits_per_sample=16
let "block_align = channels * bits_per_sample / 8"    

wave_header () { # pass file name and data size as parameters; rest are constants set elsewhere
  data_size=
  let "RIFFsize = data_size + 44 - 8"
  let "bytes_per_sec = sampleHz * block_align"

  echo -e -n "RIFF" > 
    le32 $RIFFsize 
  echo -e -n "WAVEfmt " >> 
    le32 16   # format size
    le16 1    #format tag: 1 = PCM
    le16 $channels 
    le32 $sampleHz 
    le32 $bytes_per_sec 
    le16 $block_align 
    le16 $bits_per_sample    # bits per sample
  echo -e -n "data" >> 
    le32 $data_size 
}

Display the result in hex:

以十六进制显示结果:

sampleHz=8000
milliseconds=15  # capture length 

cd /sys/bus/iio/devices/iio:device0

cat /sys/bus/iio/devices/trigger0/name > trigger/current_trigger

echo 0 > buffer/enable

echo 0 > scan_elements/in_voltage0_en  #
echo 1 > scan_elements/in_voltage1_en  #  
echo 1 > scan_elements/in_voltage2_en  # 
echo 0 > scan_elements/in_voltage3_en  #

echo $sampleHz > sampling_frequency
sampleHz=`cat sampling_frequency`  # read back actual sample rate

let "buffer_length = block_align * sampleHz * milliseconds / 1000"
echo $buffer_length > buffer/length

cd $HOME

echo 1 > /sys/bus/iio/devices/iio:device0/buffer/enable
wave_header data.wav $buffer_length
head -c $buffer_length /dev/iio:device0 >> data.wav  # LE16 data
echo 0 > /sys/bus/iio/devices/iio:device0/buffer/enable

Display the result in ascii:

以 ascii 显示结果:

$ printf "%c%c%c%c" 48 0 49 0 | hexdump

回答by Hal Sampson

A couple of more general functions to output integers:

几个更通用的函数来输出整数:

$ printf "%c" 1 | hexdump
0000000 0031                    

Use to make an audio WAV file header for iio data stream:

用于为 iio 数据流制作音频 WAV 文件头:

##代码##

Linux iio ADC data capture to WAV file:

Linux iio ADC数据采集到WAV文件:

##代码##

回答by drysdam

I don't know what's in busybox, but this might work because printf is smaller than awk.

我不知道busybox 中有什么,但这可能会起作用,因为printf 比awk 小。

##代码##

This is the output:

这是输出:

##代码##