27

My problem is that I need to create a file with this exact bytes: 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:

# 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).

What are your recommendations?

elcuco
  • 8,948
  • 9
  • 47
  • 69

6 Answers6

43

you can use the following command:

echo -n -e \\x48\\x00\\x49\\x00 > myfile
yohann.martineau
  • 1,523
  • 1
  • 17
  • 24
  • Thx. The same problem has occurred only bash is accessible inside a router. Perl and C are a dream. I use the device for rs485 communication with other slave-device and exchange works perfectly! – Orlov Const Dec 17 '19 at 15:00
  • Thanks. A thing of beauty, is a joy forever – daparic Dec 21 '19 at 13:45
  • To avoid mistakes note that with ```echo -n -e \\x48\\x00\\x49\\x00``` these are hexadecimal values. So if you want to add the LF (ASCii decimal 10) you should send \\x0a – Carles Mateo May 07 '22 at 13:07
6

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.

$ printf '\060\000\061\000' | 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:

$ printf '\110\000\111\000' | od -An -tx1
 48 00 49 00
Michael Back
  • 61
  • 1
  • 2
6

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

echo -n -e \\0060\\0000\\0061\\0000  | hexdump
flolo
  • 15,148
  • 4
  • 32
  • 57
  • ... and in hex..? is this possible? – elcuco Apr 07 '11 at 14:51
  • no, echo just accepts octal number. But you asked for a specific given hex sequence (and I even translated them into octals for you). If you are unsure how to convert look for a different hex sequence in the man page of ascii. It will give you a table with decimal, hex and octal numbers ;-). – flolo Apr 07 '11 at 14:54
  • 1
    just for future reference it does accept hex. just use \\xNN where the N is a hex number. – Velocibadgery Aug 11 '17 at 15:06
4

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

Write the binary data in hex:

# busybox printf '\x74\x65\x73\x74' > /sdcard/test.txt

Display the result in hex:

# busybox hexdump -C /sdcard/test.txt
00000000  74 65 73 74                                       |test|
00000004

Display the result in ascii:

# cat /sdcard/test.txt
test
BuvinJ
  • 10,221
  • 5
  • 83
  • 96
  • Why do you need to use to use `dd`? Why wouldn't `busybox printf '\x74\x65\x73\x74' > /sdcard/test.txt` work? – Keith Thompson Jul 19 '16 at 00:45
  • Wow you're right! I was certain that I tried that. I did try all these answers and a dozen others which all failed. It is that simple. There must have been some other variable in the mix. I'll revise my answer. Thanks! – BuvinJ Jul 19 '16 at 12:41
1

A couple of more general functions to output integers:

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

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

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

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=$2
  let "RIFFsize = data_size + 44 - 8"
  let "bytes_per_sec = sampleHz * block_align"

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

Linux iio ADC data capture to WAV file:

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
0

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

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

This is the output:

$ printf "%c" 1 | hexdump
0000000 0031                    
Chris Seymour
  • 83,387
  • 30
  • 160
  • 202
drysdam
  • 8,341
  • 1
  • 20
  • 23
  • 1
    I edited your answer with what I see, and this is not what I asked. This prints 0x31 which is the ASCII value of the character "1". – elcuco Apr 07 '11 at 14:50
  • So if you replace 1 with H and I, you get the values 0x48, 0x49 you want - instead of decimal 48/49 (using 0 and 1). The problematic part is getting zero bytes to not terminate output. The above then translates to `printf "%c%c%c%c" 72 0 73 0 | hexdump` for output 0x48 0x00 0x49 0x00. – starturtle Jun 08 '16 at 06:46